虽然JVM是一种基于栈的引擎,但Java语言没有真正提供访问栈的方式。即使在某些很少的情况下,这样做很有用。
方法的result值放在了栈里面。如果你看下面的例子:
public int method() {
if (something)
return 1;
...
if (somethingElse)
return 2;
...
return 0;
}
如果我们忽略中止异常,错误处理和其他学术性的讨论。我们能说上面这个方法“肯定”会返回1,2或0。并且这个值在跳出方法之前就放到了栈里面。
现在,有时只是当一个给定的值返回时, 它可能是一个采取某些操作的用例。人们可能被诱骗进了老式的关于多重返回语句是否邪恶的网络论战并且整个方法应该如下:
public int method() {
int result = 0;
if (something)
result = 1;
...
if (somethingElse)
result = 2;
...
// return之前的重要事件
if (result == 1337)
log.info("hehehe ;-)");
return result;
}
当然,上面的例子是错误的。因为,”if (something) return 1“和”if (something) return 2” 语句会立即中断方法执行。为了完成相同的“单一返回语句”技术,我们得这样重写代码:
public int method() {
int result = 0;
if (something)
result = 1;
else {
...
if (somethingElse)
result = 2;
else {
...
}
}
// return之前的重要事件
if (result == 1337)
log.info("hehehe ;-)");
return result;
}
我们真正想做的是用我们原始的实现在return之前查看栈里面都有什么值。比如,会返回什么值。下面是伪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 ;-)");
}
}
好消息是:是的,我们能。这里有一个简单的窍门来完成上述功能。
public int method() {
int result = 0;
try {
if (something)
return result = 1;
...
if (somethingElse)
return result = 2;
...
return result = 0;
}
// returnp之前的重要事件
finally {
if (result == 1337)
log.info("hehehe ;-)");
}
}
坏消息是:你必须永远不能忘记给result赋值。当Java语言不允许你这样做的时候,这个技术偶尔对访问方法栈非常有用。
当然你也能依靠这个无聊的解决方案:
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代码块里做更多事情而不仅仅是记录日志的话,或许你不想重构这个方法而你想要访问的不仅是返回值。
原文地址:http://blog.csdn.net/supercrsky/article/details/45970795