为什么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
区块)中执行的最后一个语句中,我已将null
分配给builder
,但我的代码打印为"In finally"
,然后"JohnIbrahim"
。任何人都可以向我解释这里发生了什么吗?
答案 0 :(得分:5)
当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;
答案 1 :(得分:3)
您将返回builder
。之后,将builder
设置为null。但它已经归还了。之后你对变量做了什么并不重要。返回值已经“锁定”。你能做的就是弄乱正在返回的对象。例如,builder.setLength(0)
会删除所有文字。
从理论上讲,您也可以从finally块中return null
,但强烈建议不要这样做(更改返回值)。
答案 2 :(得分:3)
finally
块运行之前, 返回值被评估并存储在堆栈中。请注意,堆栈上的值实际上是StringBuilder
引用的值。因此,即使您将builder
设置为null
,也不会更改已在堆栈上的已评估return
值。但是,如果返回值是对可变对象的引用,则可以改变对象,并且更改将在return
值中显示。
例如,如果您在finally
块中添加以下语句而不是nullifying
引用:
builder.append("Hrithik Roshan");
然后您将在返回值中看到该内容。
但是,如果return
builder
再次finally
阻止,则会覆盖先前评估的return
语句。但请注意,这不是一个好主意。
答案 3 :(得分:2)
finally
,除非JVM在try
块完成之前崩溃或退出。
如果try
块由于return
语句而完成,则return
的表达式在 {{1}之前被评估为单个值块执行。该值将被保存,并在finally
块完成时返回。
因此,finally
的分配无效,因为builder = null
的评估已在builder.append("Ibrahim")
执行时完成。
答案 4 :(得分:1)
builder
包含对您创建的StringBuilder的引用。执行builder = null
后,您将builder
设置为不再保留该引用。 StringBuilder本身仍然存在(至少在垃圾收集发生之前)。
正在发生的事情是你的return
语句正在返回对StringBuilder的引用。 不返回变量builder
;它返回对builder
引用的事物的引用。因此,即使您正在消除变量,return语句也已经引用了创建的对象。
如果您在builder
块中打印finally
,那么它将为空。
答案 5 :(得分:0)
执行return
的第一个执行builder.append("Ibrahim")
语句,该语句返回StringBuilder
的引用。引用被保存到堆栈中。然后执行了finally
块。您已经取消了局部变量,但在方法实际返回后,对StringBuilder
对象的引用传递给调用者。这就是打印所有值的原因。错误是您为builder
块中从未使用过的finally
分配了一个值。堆栈在实际返回之前保留return
语句操作数的值,即在finally
块之后。如果您不希望从return null
块中的finally
方法返回引用,那将覆盖堆栈中的值。
} finally {
System.out.println("In finaly"); // builder.append("-DarElBeida");
return null;
}