В то время как JVM является машиной на основе стека , язык Java на самом деле не предлагает вам никакого способа доступа к этому стеку. Даже если иногда, в редких случаях, это было бы очень полезно.
Пример
Значения результата метода помещаются в стек. Если вы посмотрите на следующий пример:
01
02
03
04
05
06
07
08
09
10
11
|
public int method() { if (something) return 1 ; ... if (somethingElse) return 2 ; ... return 0 ; } |
Если мы игнорируем проблему остановки , обработку ошибок и другие академические дискуссии, мы можем сказать, что описанный выше метод «безусловно» вернет любое значение 1
, 2
или 0
. И это значение помещается в стек перед выпрыгиванием из метода.
Теперь, иногда, это может быть вариант использования, чтобы предпринять какое-то действие, только когда возвращено данное значение результата. Тогда можно было бы заманить людей к началу старой дискуссии о пламенной войне о том, являются ли множественные операторы return
EVIL ™, и весь метод должен был быть сформулирован так:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
public int method() { int result = 0 ; if (something) result = 1 ; ... if (somethingElse) result = 2 ; ... // Important action here prior to return if (result == 1337 ) log.info( "hehehe ;-)" ); return result; } |
Конечно, приведенный выше пример неверен, потому что ранее if (something) return 1
а if (something) return 2
оператора, немедленно прерывая выполнение метода. Чтобы добиться того же с техникой «одиночный возврат-оператор», нам нужно будет переписать наш код следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
public int method() { int result = 0 ; if (something) result = 1 ; else { ... if (somethingElse) result = 2 ; else { ... } } // Important action here prior to return if (result == 1337 ) log.info( "hehehe ;-)" ); return result; } |
… И, конечно же, мы можем продолжать прятаться на велосипедах и использовать пламя, используя фигурные скобки и / или уровни отступов , что показывает, что мы ничего не получили.
Доступ к возвращаемому значению из стека
То, что мы действительно хотели сделать в нашей первоначальной реализации, это проверка непосредственно перед возвратом, чтобы увидеть, какое значение находится в стеке, т.е. какое значение будет возвращено. Вот немного псевдо-Java:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
public int method() { try { if (something) return 1 ; ... if (somethingElse) return 2 ; ... return 0 ; } // Important action here prior to return finally { if (reflectionMagic.methodResult == 1337 ) log.info( "hehehe ;-)" ); } } |
Хорошая новость: да, мы можем! Вот простой трюк, который можно сделать для достижения вышеуказанного:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
public int method() { int result = 0 ; try { if (something) return result = 1 ; ... if (somethingElse) return result = 2 ; ... return result = 0 ; } // Important action here prior to return finally { if (result == 1337 ) log.info( "hehehe ;-)" ); } } |
Менее хорошие новости: вы никогда не должны забывать явно назначать результат. Но время от времени этот метод может быть очень полезен для «доступа к стеку методов», когда язык Java на самом деле этого не позволяет.
Конечно…
Конечно, вы могли бы просто прибегнуть к этому скучному решению здесь:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
public int method() { int result = actualMethod(); if (result == 1337 ) log.info( "hehehe ;-)" ); return result; } public int actualMethod() { if (something) return result = 1 ; ... if (somethingElse) return result = 2 ; ... return result = 0 ; } |
… и, вероятно, чаще всего эта техника действительно лучше (потому что она немного более читабельна). Но иногда вы хотите сделать больше, чем просто войти в этот блок finally
, или вы хотите получить доступ не только к значению результата, и вы не хотите проводить рефакторинг метода.
Другие подходы?
Теперь твоя очередь. Какой будет ваш предпочтительный альтернативный подход (с примерами кода?) Например, используя монаду Try? Или аспекты?
Ссылка: | Как получить доступ к значению результата метода из блока finally от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и JOOQ . |