Java вернуть ссылку или объект? Вернуться, прежде чем, наконец?
Давайте рассмотрим тестовый класс
import java.util.Date;
public class TestClass {
public String finallyHappensBeforeReturn(){
try{
return "Important Message";
}finally{
finallyHappensBeforeReturn();
}
}
public String unaffectedReference(){
String message = "Important msg";
try{
return message;
}finally{
message = " meaning of life";
}
}
public Container modifiedReference(){
Container c = new Container();
c.set("Important msg");
try{
return c;
}finally{
c.set("Meaning of life");
}
}
public void timer(){
try{
System.out.println("Try time = " + new Date().getTime());
}finally{
System.out.println("Finally time = " + new Date().getTime());
}
}
class Container{
String s;
void set(String s){
this.s = s;
}
String get(){
return s;
}
}
}
Если мы создадим основной метод следующим образом:
public static void main(String[] args){
TestClass instance = new TestClass();
instance.timer();
}
Мы можем ясно увидеть результат, который предполагает, что попытка произойдет раньше, наконец, как мы и ожидали. Распечатка времени для большинства из нас бессмысленна, поскольку на моей, как и на большинстве других машин, метод будет выполняться менее чем за миллисекунду, но, тем не менее, я полагал, что я его включу.
Если мы изменим основной на
public static void main(String[] args){
TestClass instance = new TestClass();
System.out.println(instance.unaffectedReference());
}
мы печатаем "Важное сообщение", которое предполагает, что unafferedReference() возвращает ссылку на строковый литерал "Imporant msg", мы печатаем его на консоль, и только после этого указатель меняется на указатель на объект String "Значение жизни". Имеет смысл до сих пор.
Однако, если мы изменим главное на
public static void main(String[] args){
TestClass instance = new TestClass();
System.out.println(instance.modifiedReference().get());
}
мы получаем "смысл жизни". Обратите внимание, что мы не храним ссылку на возвращаемый объект ContainerifiedReference(). Итак, если бы это было
public static void main(String[] args){
TestClass instance = new TestClass();
Container container = instance.modifiedReference();
System.out.println(container.get());
}
это имело бы смысл. modifierReference() возвращает ссылку, затем переходит в finally{}, изменяет ссылку на объект, ну, ну, ссылки - и только тогда значение печатается. Что там произошло? наконец выполняется перед System.out.print(), но ПОСЛЕ возврата? Как это возможно?
И, последний пример -
public static void main(String[] args){
TestClass instance = new TestClass();
System.out.println(instance.finallyHappensBeforeReturn());
}
В этом случае мы получаем StackruError, который также предполагает, что наконец произойдет до возврата. Обратите внимание, что "Важное сообщение" никогда не печатается до выдачи исключения.
Итак, вопрос в том, что было первым - наконец или возвращение?
1 ответ
Не имеет ничего общего с тем, что выполняется после чего (это try, catch, return, finally - наконец, запускается после return, но до того, как метод действительно возвращается, так что он технически МОЖЕТ изменить возвращаемое значение - просто не стоит сделай это). Основное - знать, что String неизменен.
public String unaffectedReference(){
String message = "Important msg";
try{
return message;
}finally{
message = " meaning of life";
}
}
Это вернет "Важное сообщение", затем изменит сообщение (в методе) на "смысл жизни". Но возвращаемое значение является ссылкой на строку "Важное сообщение", а не "сообщение". Если строка не была неизменной, и вы должны были сделать, например, message.setValue("смысл жизни"), то это будет распечатано.
public Container modifiedReference(){
Container c = new Container();
c.set("Important msg");
try{
return c;
}finally{
c.set("Meaning of life");
}
}
... ваше возвращаемое значение является ссылкой на объект Container, и, изменяя что-то ВНУТРИ, этот объект Container изменяет возвращаемое значение, конечно, потому что вы возвращаете объект, и этот объект изменяется.