【问题标题】:try / finally block question尝试/最终阻止问题
【发布时间】:2011-03-29 18:48:00
【问题描述】:

发现这个问题here

我不明白,为什么在第一种情况下打印CoolReturn+1 而在第二种情况下打印CoolReturn?它是如何工作的?

谢谢

=====================

将打印什么?

public void testFinally(){
    System.out.println(setOne().toString());

}

protected StringBuilder setOne(){
    StringBuilder builder=new StringBuilder();
    try{
        builder.append("Cool");
        return builder.append("Return");
    }finally{
        builder.append("+1");
    }
}

答案:CoolReturn+1

有点难:

public void testFinally(){
    System.out.println(setOne().toString());

}

protected StringBuilder setOne(){
    StringBuilder builder=new StringBuilder();
    try{
        builder.append("Cool");
        return builder.append("Return");
    }finally{
        builder=null;  /* ;) */
    }
}

答案:CoolReturn

【问题讨论】:

标签: java try-catch


【解决方案1】:

考虑

protected StringBuilder setOne(){
    StringBuilder builder=new StringBuilder();
    try{
        builder.append("Cool");
        return builder.append("Return");
    }finally{
        builder.append("+1");
    }
}

作为

protected StringBuilder setOne(){
    StringBuilder builder=new StringBuilder();
    try{
        builder.append("Cool");
        StringBuilder ret = builder.append("Return"); // 1
        return ret; // 2
    }finally{
        builder.append("+1"); //3
    }
}

第 1 行被执行,builder 作为结果返回。然后执行第 3 行,builder+1 附加,然后返回ret,它是对builder 引用的对象的“引用”。第二种情况也是如此。希望清楚。

【讨论】:

  • 它不是构建器对对象引用的引用。它是参考的副本。如果它是一个引用,那么它也将被设置为 null。
【解决方案2】:

第一个:

finally 总是会触发(假设机器没有崩溃或任何事情)。因此,在返回之后,finally 块会触发,并且由于它引用了对象“builder”,因此它会将额外的标记附加到它。

第二个:

finally 块像以前一样触发,但是它将对 builder 的引用设置为 null。该对象仍然存在,因为它仍然有指向它的链接。

【讨论】:

    【解决方案3】:

    当它确实返回 builder.append("Return") 时,对 builder 变量的引用的副本被推送到堆栈上。然后将builder设置为null。然后调用者将引用的副本从堆栈中弹出。

    【讨论】:

      【解决方案4】:

      在第一个示例中,在 finally 块中,您使用 append 操作字符串构建器。

      在第二个示例中,在 finally 块中,在从 append 方法返回结果之后,将指向字符串生成器的指针更改为空指针。这不会以任何方式修改您以前指向的字符串生成器。

      编辑:看起来我被打败了。

      【讨论】:

        【解决方案5】:

        这是因为return 表达式在finally 块执行之前被评估。当您在代码的return 语句中调用一个方法并将日志语句添加到您的tryfinally 块时,这一点非常明显。相关解释可以在JLS 3rd edition, 14.20.2中找到。这就是为什么 finally 块中的 return 语句会在 Eclipse 等 IDE 中产生警告的原因之一。

        一个示例 groovy 代码:

        def doSomething() {
            def f = "something";
            try {
                return f += doSomethingMore()
            } finally {
                println "before nulling";        
                f = null;
                println "after nulling";
            }
        }
        
        def doSomethingMore() {
            println "doSomethingMore called"
            return "-wow";
        }
        
        println "output from call ---> " + doSomething()
        

        【讨论】:

          【解决方案6】:

          finally 运算符始终运行,因此返回 builder,然后返回 +1。

          在第二个中,builder 设置为 null,因此没有其他内容可以添加。也可以很容易地在最后一个中使用 builder = ""。

          【讨论】:

            【解决方案7】:

            finally 块将始终执行。 http://download.oracle.com/javase/tutorial/essential/exceptions/finally.html 这就是所有三个语句都附加的原因。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-11-17
              • 2013-08-10
              • 2014-01-09
              • 2017-11-05
              • 2021-05-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多