[英]Why StringBuilder does not print?
Why StringBuilder does not print what it should print in a small code 为什么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();
}
}
In the last statement executed in setFin()
(in the finally
block) I have assigned null
to builder
, but my code prints "In finally"
and then "JohnIbrahim"
. 在setFin()
执行的最后一个语句(在finally
块中)我已经为builder
分配了null
,但是我的代码打印"In finally"
,然后是"JohnIbrahim"
。 Can anybody explain to me what is going on here? 任何人都可以向我解释这里发生了什么吗?
When there is a return
statement inside the try
block, it will execute the finally
block before actually returning. 当try
块内有return
语句时,它将在实际返回之前执行finally
块。
And the method doesn't return null
because the return
statement holds a reference to the actual StringBuilder object, not to the variable builder
. 并且该方法不返回null
因为return
语句包含对实际StringBuilder对象的引用,而不是对变量builder
的引用。
Setting builder == null
doesn't delete the StringBuilder itself, it just drops builder
's reference to it. 设置builder == null
不会删除StringBuilder本身,它只是删除了builder
对它的引用。
This behavior can be confusing. 这种行为可能令人困惑。 To make things clear it could be helpful to return from outside the try/catch/finally block: 为了清楚起见,从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;
You are returning builder
. 你正在回归builder
。 After that you set builder
to null. 之后,将builder
设置为null。 But it has already been returned. 但它已经归还了。 It does not matter what you do to the variable afterwards. 之后你对变量做了什么并不重要。 The return value is already "locked-in". 返回值已经“锁定”。 What you could do is mess with the object that is being returned. 你能做的就是弄乱正在返回的对象。 For example, builder.setLength(0)
will remove all text to it. 例如, builder.setLength(0)
将删除所有文本。
In theory, you could also return null
from the finally block, but that (changing the return value) is highly discouraged. 从理论上讲,您也可以从finally块return null
,但强烈建议不要(更改返回值)。
Return value is evaluated and stored on the stack , before the finally
block runs. 在finally
块运行之前,将评估返回值并将其存储在堆栈中 。 Note that the value on the stack is actually the value of the StringBuilder
reference. 请注意,堆栈上的值实际上是StringBuilder
引用的值。 So, even if you set the builder
to null
, that doesn't changes the evaluated return
value already on the stack. 因此,即使您将builder
设置为null
,也不会更改堆栈上已有的计算return
值。 However, if the return value is a reference to an mutable object, you can mutate the object, and the changes will be visible in return
value. 但是,如果返回值是对可变对象的引用,则可以改变对象,并且更改将在return
值中可见。
For eg, if you add the below statement in the finally
block instead of nullifying
the reference: 例如,如果在finally
块中添加以下语句而不是nullifying
引用nullifying
:
builder.append("Hrithik Roshan");
then you will see that content in the return value. 然后你会在返回值中看到该内容。
However, if you return
the builder
again, from finally
block, it will overright the previous evaluated return
statement. 但是,如果再次从finally
块return
builder
,它将覆盖先前计算的return
语句。 But mind you it's not a good idea. 但请注意,这不是一个好主意。
finally
is always executed, unless the JVM crashes or exits before the try
block finishes. finally
总是执行,除非JVM在try
块完成之前崩溃或退出。
If the try
block completes due to a return
statement, the expression of the return
is evaluated into a single value before the finally
block executes. 如果try
块由于return
语句而完成,则在finally
块执行之前 ,将return
的表达式计算为单个值。 That value is saved, and returned when the finally
block completes. 该值被保存,并在finally
块完成时返回。
Thus, the assignment of builder = null
has no effect because the evaluation of builder.append("Ibrahim")
is already finished by the time the finally
executes. 因此, builder = null
的赋值没有任何效果,因为builder.append("Ibrahim")
的评估已经在finally
执行时完成。
builder
holds a reference to the StringBuilder that you've created. builder
包含对您创建的StringBuilder的引用。 When you do builder = null
, you're setting builder
to no longer hold that reference. 当您执行builder = null
,您将builder
设置为不再保留该引用。 The StringBuilder itself still exists (at least until garbage collection occurs). StringBuilder本身仍然存在(至少在垃圾收集发生之前)。
What's happening is that your return
statement is returning a reference to the StringBuilder. 发生的事情是你的return
语句返回对StringBuilder的引用。 It's not returning the variable builder
; 它没有返回变量builder
; it's returning a reference to the thing that builder
refers to. 它返回对builder
引用的东西的引用。 So even though you're wiping out the variable, the return statement already has a reference to the created object. 因此,即使您正在消除变量,return语句也已经引用了创建的对象。
If you printed builder
in your finally
block, it would be null there. 如果在finally
块中打印了builder
,那么它将为null。
First executed return
statement which execute builder.append("Ibrahim")
that returns the reference of StringBuilder
. 第一个执行的return
语句,它执行返回StringBuilder
引用的builder.append("Ibrahim")
。 The referece is saved to the stack. 引用被保存到堆栈中。 Then excuted the finally
block. 然后执行了finally
阻止。 You have nulled the local variable, but the reference to StringBuilder
object passed to the caller after the method actually return. 您已经取消了局部变量,但在方法实际返回后, StringBuilder
对象的引用传递给调用者。 That's why printed all values. 这就是打印所有值的原因。 The error is that you assign a value to the builder
in finally
block that is never used. 错误是您为finally
块中的builder
分配了一个从未使用过的值。 The stack keeps the value of the return
statement operand before it actually returned, ie after finally
block. 堆栈在实际返回之前保持return
语句操作数的值,即在finally
块之后。 If you don't want to return reference from the method you should return null
in the finally
block, that will override the value in the stack. 如果您不想从方法返回引用,则应在finally
块中return null
,这将覆盖堆栈中的值。
} finally {
System.out.println("In finaly"); // builder.append("-DarElBeida");
return null;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.