How to Access a Method’s Result Value From the Finally Block
While the JVM is a stack-based machine, the Java language doesn’t really offer you any way to access that Stack. Even if sometimes, in rare occasions, it would be very useful.
An example
Method result values are put on the stack. If you look at the following example:
public int method() { if (something) return 1; ... if (somethingElse) return 2; ... return 0; }
If we ignore the halting problem, error handling, and other academic discussions, we can say that the above method will “certainly” return any value of 1
, 2
, or 0
. And that value is put on the stack prior to jumping out of the method.
Now, sometimes, it may be a use-case to take some action only when a given result value is returned. People might then be lured into starting the old flame-war discussion about whether multiple return
statements are EVIL™ and the whole method should have been phrased like this, instead:
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; }
Of course, the above example is wrong, because, previously, the if (something) return 1
and if (something) return 2
statements immediately aborted method execution. In order to achieve the same with the “single-return-statement” technique, we’ll have to rewrite our code like this:
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; }
… and, of course, we can continue bike-shedding and flame-waring the use of curly braces and/or indentation levels, which shows we haven’t gained anything.
Accessing the return value from the stack
What we really wanted to do in our original implementation is a check just before returning to see what value is on the stack, i.e. what value will be returned. Here’s some pseudo-Java:
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 ;-)"); } }
The good news is: Yes we can! Here’s a simple trick that can be done to achieve the above:
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 ;-)"); } }
The less good news is: You must never forget to explicitly assign the result. But every once in a while, this technique can be very useful to “access the method stack” when the Java language doesn’t really allow you to.
Of course…
Of course you could also just resort to this boring solution here:
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; }
… and probably, most often, this technique is indeed better (because slightly more readable). But sometimes, you want to do more stuff than just logging in that finally
block, or you want to access more than just the result value, and you don’t want to refactor the method.
Other approaches?
Now it’s your turn. What would be your preferred, alternative approach (with code examples?) E.g. using a Try monad? Or aspects?
Reference: | How to Access a Method’s Result Value From the Finally Block from our JCG partner Lukas Eder at the JAVA, SQL, AND JOOQ blog. |