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 изменяет возвращаемое значение, конечно, потому что вы возвращаете объект, и этот объект изменяется.

Другие вопросы по тегам