Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.89/19: Рейтинг темы: голосов - 19, средняя оценка - 4.89
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18

TRICKS: Что вернёт метод?

17.02.2014, 13:39. Показов 3797. Ответов 42

Студворк — интернет-сервис помощи студентам
начинаем серию постов TRICKS по фишкам JVM и компилятора, вопросы для самообразования, не более

просьба не компилировать, а попробовать подумать что вернёт метод

Java
1
2
3
4
5
6
7
8
9
10
    static String dubleReturn() {
        while (true) {
            try {
                return "foo";
            } finally {
                break;
            }
        }
        return "boo";
    }
а после того как скомпилите и увидите результат, прошу объяснить почему именно так

ps: вопрос чисто академический, поэтому не стоит нести чушь про то что так писать негоже
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.02.2014, 13:39
Ответы с готовыми решениями:

TRICKS: Что нам грядущая 8-чка готовит
допустим у нас есть List l = new ArrayList() { { for (int i = 0; i < 10; i++) { ...

Пример, когда метод Thread.isAlive() вернёт false
Приведите, пожалуйста, два примера. Такие, что бы в первом main thread при вызове на ней метода isAlive(); вернула false, а во втором...

Reflection: что вернет getField.getInt(null)?
У Хорстмана наткнулся на следующую строку: return JOptionPane.class.getField(s).getInt(null); И все не могу сообразить, что оно вернуть...

42
 Аватар для IVIakCollideR
40 / 40 / 14
Регистрация: 26.12.2013
Сообщений: 309
17.02.2014, 16:24
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от mutagen Посмотреть сообщение
просьба не компилировать, а попробовать подумать что вернёт метод
метод вернул boo как никак, и это довольно логично c его стороны, потому что стековый фрейм общий для всех значение в данном случае, а финалли сработает любой ценой, попросту после отработкт финалли части имеем return foo, но оно затирается вызовом return boo, поскольку я уже сказал - место для строчной константы одно на двоих
0
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
17.02.2014, 16:26  [ТС]
Цитата Сообщение от IVIakCollideR Посмотреть сообщение
попросту после отработкт финалли части имеем return foo
не имеем, так как после окончания finally указатель ДОЛЖЕН вернуться на первый return что нам и демонстрирует код
Java
1
2
3
4
5
6
7
static String tryFinally() {
        try {
            return "foo";
        } finally {
            System.out.println("finally");
        }
    }
по вашей "имеем" мы должны оказаться за блоком try finally и ничего не вернуть
0
46 / 36 / 15
Регистрация: 05.02.2014
Сообщений: 140
17.02.2014, 16:35
Цитата Сообщение от IVIakCollideR Посмотреть сообщение
метод вернул boo как никак, и это довольно логично c его стороны, потому что стековый фрейм общий для всех значение в данном случае, а финалли сработает любой ценой, попросту после отработкт финалли части имеем return foo, но оно затирается вызовом return boo, поскольку я уже сказал - место для строчной константы одно на двоих
Вся фишка в break.

Добавлено через 7 минут
можно еще так сделать:
Java
1
2
3
4
5
6
7
8
9
10
11
12
    static String dubleReturn() {
        String str = "doo";
        while (true) {
            try {
                return str;
            } finally {
                str += " boo";
                //break;
            }
        }
        //return str;
    }
и убрать комментирование
0
 Аватар для IVIakCollideR
40 / 40 / 14
Регистрация: 26.12.2013
Сообщений: 309
17.02.2014, 16:38
Цитата Сообщение от mutagen Посмотреть сообщение
Код Java(TM) 2 Platform Standard Edition 5.0
1
2
3
4
5
6
7
static String tryFinally() {
* * * * try {
* * * * * * return "foo";
* * * * } finally {
* * * * * * System.out.println("finally");
* * * * }
* * }
по вашей "имеем" мы должны оказаться за блоком try finally и ничего не вернуть
нет, все правильно, у вас же 1 ретурн в этом коде, значит возвращает именно он, но в прошлом примере было 2 ретурна, второй обязан выполниться потому что инструкция должна бить прочитана после блока финалли и если там ничего нет, - управление передается к первому ретурну, а если там что то еще есть, как в нашем случае - второй ретурн, то он выполняется и перезаписывает значение новым - своим, поскольку они оба занимают место для 1 константы.

если вставить System.exit(1); перед ретурном(вторым) в первой задачке, то можно увидеть что на данный момент будет в стеке, а именно - foo/
0
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
17.02.2014, 16:46  [ТС]
Цитата Сообщение от RomanovD Посмотреть сообщение
Вся фишка в break.
это не фишка а баг и в байткоде удаляется первый ретурн, чё бы вы не наделали с переменными его просто нет )

Добавлено через 6 минут
Цитата Сообщение от IVIakCollideR Посмотреть сообщение
второй обязан выполниться потому что инструкция должна бить прочитана после блока финалли и если там ничего нет
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   
 for (int i = 0; i < 10; i++) {
            System.out.println(goodDoubleRet());
        }
 
  static int goodDoubleRet() {
        Random r = new Random();
        try {
            if (r.nextInt(2) == 1) {
                return 1;
            }
        } finally {
            System.out.println("fin");
        }
        return 2;
    }
попробуйте скомпилить, странно да - имеем 2 ретурна, но если в 1 в ифке тру то до второго не добираемся, хотя файнал пашет всегда
0
3 / 3 / 1
Регистрация: 18.09.2013
Сообщений: 19
17.02.2014, 17:03
Цитата Сообщение от mutagen Посмотреть сообщение
это не фишка а баг и в байткоде удаляется первый ретурн, чё бы вы не наделали с переменными его просто нет )

Добавлено через 6 минут

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   
 for (int i = 0; i < 10; i++) {
            System.out.println(goodDoubleRet());
        }
 
  static int goodDoubleRet() {
        Random r = new Random();
        try {
            if (r.nextInt(2) == 1) {
                return 1;
            }
        } finally {
            System.out.println("fin");
        }
        return 2;
    }
попробуйте скомпилить, странно да - имеем 2 ретурна, но если в 1 в ифке тру то до второго не добираемся, хотя файнал пашет всегда
Ничего странного я не вижу. Все пашет как и должно пахать.
Если бы работало как вы описываете по спекам, то действительно был бы баг (до спек не добрался, но боюсь у вас не верная интерпретация), потому что в этом случае мы полностью игногрировали бы break.
Я считаю, что разработчики java все сделали логично. Приоритет оставлен за последним оператором.
0
46 / 36 / 15
Регистрация: 05.02.2014
Сообщений: 140
17.02.2014, 17:06
это не фишка а баг и в байткоде удаляется первый ретурн, чё бы вы не наделали с переменными его просто нет )
Наверное он удаляется по той же причине, по которой удаляется return в следующем коде:
Java
1
2
3
4
static String dubleReturn() {
        if (false) return "foo";
        return "doo";
}
Java
1
2
3
4
5
6
7
static dubleReturn()Ljava/lang/String;
   L0
    LINENUMBER 6 L0
    LDC "doo"
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 0
Мы просто никогда его не выполним, поэтому его и нет.
0
 Аватар для IVIakCollideR
40 / 40 / 14
Регистрация: 26.12.2013
Сообщений: 309
17.02.2014, 17:12
Цитата Сообщение от mutagen Посмотреть сообщение
странно да 2 ретурна, но если в 1 в ифке тру то до второго не добираемся
а вы про брейк не забыли в файнали? именно он и передает управление на следующую строку после цыкла,
в первом примере думаю было бы то же самое без брейка
0
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
17.02.2014, 18:09  [ТС]
Цитата Сообщение от RomanovD Посмотреть сообщение
Наверное он удаляется по той же причине, по которой удаляется return в следующем коде:
именно - это называется работа оптимизатора, и в этом случае всё ок

Цитата Сообщение от IVIakCollideR Посмотреть сообщение
а вы про брейк не забыли в файнали? именно он и передает управление на следующую строку после цыкла,
я вижу вам всё равно и логика и отсутствие в байткоде ретурна - только бы доказать своё мнение )
хорошо что тут есть Skipy который показал что там в байткоде, но я уверен и без этого нашлись бы люди которые утверждали бы что затереть успешный ретурн это нормально )))
думаю на этом можно эту темку завершить, но не переключайте канал, я ещё подкину задачек )
0
 Аватар для IVIakCollideR
40 / 40 / 14
Регистрация: 26.12.2013
Сообщений: 309
17.02.2014, 19:32
Цитата Сообщение от mutagen Посмотреть сообщение
только бы доказать своё мнение )
есть такой косяк, заранее прошу понять и простить если что
Цитата Сообщение от mutagen Посмотреть сообщение
хорошо что тут есть Skipy который показал что там в байткоде, но я уверен и без этого нашлись бы люди которые утверждали бы что затереть успешный ретурн это нормально )))
я выразил свою точку зрения, то как это работает - весьма логично, многие ответили так, да и результат работы программы = boo, Вопрос был ведь не как правильно/неправильно, а конкретным -
Цитата Сообщение от mutagen Посмотреть сообщение
что вернёт метод
.
В следующий раз будем глубже углубляться в сторону логики)
0
 Аватар для KuKu
1563 / 1041 / 94
Регистрация: 17.04.2009
Сообщений: 2,995
17.02.2014, 19:56
Цитата Сообщение от IVIakCollideR Посмотреть сообщение
а конкретным -
Тут два варианта - выбор не велик
0
3 / 3 / 1
Регистрация: 18.09.2013
Сообщений: 19
18.02.2014, 12:31
Для интереса проверил, а как же реализуют этот код другие языки.

Delphi не компилиться и выдает ошибку
E2126 Cannot BREAK, CONTINUE or EXIT out of a FINALLY clause

C# то же не компилиться
Control cannot leave the body of a finally clause

Как видно здесь даже не пытались разрешить конфликтную ситуацию, что игнорировать return или break,
просто запретили.

Добавлено через 12 минут
Цитата Сообщение от mutagen Посмотреть сообщение
не имеем, так как после окончания finally указатель ДОЛЖЕН вернуться на первый return что нам и демонстрирует код
Java
1
2
3
4
5
6
7
static String tryFinally() {
        try {
            return "foo";
        } finally {
            System.out.println("finally");
        }
    }
по вашей "имеем" мы должны оказаться за блоком try finally и ничего не вернуть
Это совершенно разные ситуации. В вашем случае в finally есть оператор влияющий на порядок выполнения (break). А в случае выше таких операторов нет.

Как по вашему должет работать код?

Java
1
2
3
4
5
6
7
while (true) {
            try {
                return "foo";
            } finally {
                return "too";
            }
        }
0
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
18.02.2014, 13:28  [ТС]
Цитата Сообщение от vladimirsky Посмотреть сообщение
Как по вашему должет работать код?
выполнится первым тот что в файнале и выполнит ретурн "тоо", это же очевидно - так как файнал выполняется первы всегда, никто у него ничего не перехватит
Цитата Сообщение от vladimirsky Посмотреть сообщение
В вашем случае в finally есть оператор влияющий на порядок выполнения (break).
это же не должно влиять на успешный ретурн, не так ли или должно, как вы считаете ?
логично ли что операция с низким приоритетом брейк влияет на операцию с высоким приоритетом ретурн?
0
3 / 3 / 1
Регистрация: 18.09.2013
Сообщений: 19
18.02.2014, 15:07
Цитата Сообщение от mutagen Посмотреть сообщение
это же не должно влиять на успешный ретурн, не так ли или должно, как вы считаете ?
логично ли что операция с низким приоритетом брейк влияет на операцию с высоким приоритетом ретурн?
Я не слышал, что есть приоритет операторов перехода в java.
По-моему работает принцип, кто последний тот и прав.
0
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
18.02.2014, 15:22  [ТС]
ок - не совсем верная формулировка, не приоритет, а скажем вернее так:
уже выполнившаяся операция return прерывается операцией break
как же быть с этим?

Java
1
2
3
4
5
6
7
8
9
10
11
12
static void tst() {
        while (true) {
            if (1 == 1) {
                System.out.println(1);
                return ;
            }
            System.out.println(3);
            break;
        }
        System.out.println(2);
        return;
    }
кто тут последний?
0
3 / 3 / 1
Регистрация: 18.09.2013
Сообщений: 19
18.02.2014, 15:41
Цитата Сообщение от mutagen Посмотреть сообщение
ок - не совсем верная формулировка, не приоритет, а скажем вернее так:
уже выполнившаяся операция return прерывается операцией break
как же быть с этим?

Java
1
2
3
4
5
6
7
8
9
10
11
12
static void tst() {
        while (true) {
            if (1 == 1) {
                System.out.println(1);
                return ;
            }
            System.out.println(3);
            break;
        }
        System.out.println(2);
        return;
    }
кто тут последний?
Первый оператор return. До остальных код просто не добирается.

На счет "выполнившаяся" операция return. То здесь она еще не выполнилась. Иначе мы уже бы покинули функцию. Еще надо выполнить finally, но мы ЯВНО меняем ход выполнения программы.
А если бы в finally был exception, как поступать в этом случае. По вашему return вроде как и выполнен.

Я понимаю, что Вы хотите мне показать, но считаю теперешнее поведение кода правильным.

BTW. За TRICKS рассылку, спасибо. Очень помогает для "шлифовки" знаний.
0
 Аватар для verylazy
462 / 462 / 71
Регистрация: 26.02.2013
Сообщений: 1,263
18.02.2014, 16:10
я тут нашел кое что на сайте оракла
и там прямо в первом абзаце получите ответ
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.
То есть получается finally и был задуман для перехвата внезапно сделать оп оп return;
0
 Аватар для KuKu
1563 / 1041 / 94
Регистрация: 17.04.2009
Сообщений: 2,995
18.02.2014, 16:17
Имхо, это не совсем то. Он задуман сделать оп-оп даже если тогда, когда был return. А не делать return самому. По-хорошему надо было запретить эти return/break в finally. Поздно спохватились скорее всего, а тут и обратную совместимость надо оставить.
0
 Аватар для verylazy
462 / 462 / 71
Регистрация: 26.02.2013
Сообщений: 1,263
18.02.2014, 16:24
Я именно это и имел ввиду просто выразился непонятно.
У меня эклипс вообще ругается на break в finally
0
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
18.02.2014, 16:32  [ТС]
Цитата Сообщение от vladimirsky Посмотреть сообщение
считаю теперешнее поведение кода правильным.
Цитата Сообщение от verylazy Посмотреть сообщение
when the try block exits.
это ключевая нескладуха, так как ретурн был в трай и этот блок отработал успешно и без экцепов по всем нормам человеческого языка ))) По всем соглашениям и докам после отработки финализации, мы обязаны были вернуть управление на return, так как он уже был выполнен и ожидает возврата из файнала
Цитата Сообщение от verylazy Посмотреть сообщение
try block exits
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
18.02.2014, 16:32
Помогаю со студенческими работами здесь

Что вернет length для двумерного массива?
я Java не изучаю.но анализируя один код на Java у меня возник вопрос. допустим задан двухмерный массив int mass какое значение...

Передать в метод "что-то", что бы метод мог в это "что-то" записать матрицу неизвестной размерности
Опишу суть проблемы подробнее. Есть метод, который умножает две матрицы, мне бы хотелось, что бы метод принимал в параметрах: 1....

Что вернёт метод простого класса
доброго времени суток. Имеем простой класс. import android.accounts.Account; import android.accounts.AccountManager; import...

Что вернет функция
Что вернет функция, проверяющая баланс скобок, если она принимает как параметр такую строку: ((х+y/z+у+(z/(y+z))-((0*z)-3) ...

Что вернет функция
Здравствуйте! Я вот С не знаю вообще, подскажите пожалуйста выполнится ли while при таком условии if (array_size == 0) return (0);...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20%
Дальние перспективы сервера - слоя сети с космологическим дизайном интефейса карты и логики.
Hrethgir 07.04.2026
Дальнейшее ближайшее планирование вывело к размышлениям над дальними перспективами. И вот тут может быть даже будут нужны оценки специалистов, так как в дальних перспективах всё может очень сильно. . .
Горе от ума
kumehtar 07.04.2026
Эта мне ментальная установка, что вот прямо сейчас, мол, мне для полного счастья не хватает (нужное вписать), и когда я этого достигну - тогда и полный кайф. Одна из самых сильных ловушек на пути. . . .
Использование значений реквизитов справочника в документе, с определенными условиями и правами
Maks 07.04.2026
1. Контроль срока действия договора Алгоритм из решения ниже реализован на примере нетипового документа "ЗаявкаНаРаботу", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если. . .
Доступность команды формы по условию
Maks 07.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: сделать доступной кнопку (команда формы "ЗавершитьСписание") при. . .
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru