6

为什么 StringBuilder 不打印应该在小代码中打印的内容

public final class Test1 {

    public void test() {
        System.out.println(setFin().toString());
    }

    protected StringBuilder setFin() {
        StringBuilder builder = new StringBuilder();
        try {
            builder.append("John");
            return builder.append("Ibrahim");
        } finally {
            System.out.println("In finaly");  // builder.append("-DarElBeida");
            builder = null;
        }
    }     

    public static void main(String args[]){
        new Test1().test();
    }
}

setFin()(在finally块中)执行的最后一条语句中,我已分配nullbuilder,但我的代码打印"In finally"然后"JohnIbrahim". 谁能向我解释这里发生了什么?

4

6 回答 6

6

当块内有return语句时,它会在实际返回之前try执行该块。finally

并且该方法不会返回null,因为该return语句包含对实际StringBuilder对象的引用,而不是对变量的引用builder

设置builder == null不会删除StringBuilder本身,它只是删除对它builder的引用。

这种行为可能会令人困惑。为了清楚起见,从 try/catch/finally 块之外返回可能会有所帮助:

StringBuilder builder = new StringBuilder();

try {
    builder.append("John");
    builder.append("Ibrahim");
} finally {
    System.out.println("In finaly");  // builder.append("-DarElBeida");
    builder = null;
}

return builder;
于 2013-08-04T12:32:02.120 回答
3

你回来了builder。之后,您设置builder为空。但它已经被退回了。之后你对变量做了什么并不重要。返回值已经“锁定”了。您可以做的是弄乱正在返回的对象。例如,builder.setLength(0)将删除所有文本。

理论上,您也可以return null从 finally 块开始,但非常不鼓励这样做(更改返回值)。

于 2013-08-04T12:34:41.520 回答
3

在块运行之前,返回值被评估并存储在堆栈中。finally注意栈上的值其实就是StringBuilder引用的值。因此,即使您将 设置buildernull,也不会更改return已经在堆栈上的评估值。但是,如果返回值是对可变对象的引用,您可以改变该对象,并且更改将在return值中可见。

例如,如果您在finally块中添加以下语句而不是nullifying引用:

builder.append("Hrithik Roshan");

然后您将在返回值中看到该内容。

但是,如果您再次使用 fromreturn块,它将覆盖先前的评估语句。但请注意,这不是一个好主意。builderfinallyreturn

于 2013-08-04T12:36:01.873 回答
2

finally始终执行,除非 JVM 在try块完成之前崩溃或退出。

如果try块由于return语句而完成,则在块执行之前将的表达式return评估为单个值。该值被保存,并在块完成时返回。finallyfinally

因此,赋值没有任何效果,因为在执行时已经完成builder = null了评估。builder.append("Ibrahim")finally

于 2013-08-04T12:36:36.973 回答
1

builder保存对您创建的 StringBuilder 的引用。当您这样做时builder = null,您将设置builder为不再持有该参考。StringBuilder 本身仍然存在(至少在垃圾收集发生之前)。

发生的事情是您的return语句正在返回对 StringBuilder 的引用。它没有返回变量builder;它返回对所指事物的builder引用。因此,即使您正在清除变量,return 语句也已经引用了创建的对象。

如果你builder在你的finally块中打印,它会在那里为空。

于 2013-08-04T12:36:55.593 回答
0

第一个执行的return语句,它执行builder.append("Ibrahim")返回的引用StringBuilder。参考被保存到堆栈中。然后执行finally块。您已经使局部变量为空,但是StringBuilder在方法实际返回之后传递给调用者的对象的引用。这就是打印所有值的原因。错误是您为从未使用过的builderinfinally块分配了一个值。堆栈return在它实际返回之前,即在finally块之后保存语句操作数的值。如果你不想从你应该return nullfinally块中的方法返回引用,那将覆盖堆栈中的值。

} finally {
  System.out.println("In finaly");  // builder.append("-DarElBeida");
  return null;

}
于 2013-08-04T12:37:28.113 回答