Форум программистов, компьютерный форум, киберфорум
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. Показов 3653. Ответов 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
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru