Why doesn't StringBuilder print?

Why doesn't StringBuilder print what it should print in small code

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 done in setFin() (in the finally block), I assigned null to builder , but my code prints "In finally" and then "JohnIbrahim" . Can someone explain to me what is going on here?

+6
source share
6 answers

When there is a return in the try block, it will execute the finally block until the actual return.

And the method does not return null , because the return contains a reference to the actual StringBuilder object, and not to the builder variable.

The builder == null parameter does not delete StringBuilder itself, it just drops the builder link.

This behavior can be misleading. To make everything clear, it would be useful to return from outside the try / catch / finally block:

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

You return the builder . After that, you set the builder parameter to null. But he has already been returned. After that, it doesn't matter what you do with the variable. The return value is already "locked". What you can do is mess with the returned object. For example, builder.setLength(0) will delete all text.

In theory, you could also return null from the finally block, but this (changing the return value) is very discouraged.

+3
source

The return value is evaluated and stored on the stack before the finally block is executed. Note that the value on the stack is actually the value of the StringBuilder reference. Thus, even if you set builder to null , this will not change the estimated return value already on the stack. However, if the return value is a reference to a mutable object, you can mutate the object, and the changes will be visible in the return value.

For example, if you add the statement below to the finally block instead of the nullifying link:

 builder.append("Hrithik Roshan"); 

then you will see this content in the return value.

However, if you return builder again, from the finally block, it will be on top of the previous evaluated return . But remember, this is not a good idea.

+3
source

finally always executed if the JVM fails or fails before the try block completes.

If the try block completes due to the return , the return expression evaluates to a single value before the finally block is executed. This value is saved and returned when the finally block completes.

Thus, the assignment of builder = null not affected, because the evaluation of builder.append("Ibrahim") already complete by the time final is complete.

+2
source

builder contains a link to the created StringBuilder. When you do builder = null , you set builder to no longer hold this link. StringBuilder itself still exists (at least until garbage collection).

What happens is that your return returns a reference to StringBuilder. It does not return the builder variable; it returns a link to the thing the builder belongs to. Therefore, even if you destroyed the variable, the return statement already refers to the created object.

If you typed builder in your finally block, it will be empty.

+1
source

First, the return is executed, which executes builder.append("Ibrahim") , which returns a StringBuilder reference. The referee is saved on the stack. Then I read the finally block. You specified a local variable, but a reference to the StringBuilder object StringBuilder passed to the caller after the method actually returns. That is why all values ​​are printed. The error is that you are assigning a value to the builder in finally block, which is never used. The stack saves the value of the operand of the return until it actually returns, i.e. After finally . If you do not want to return a reference from a method, you must return null in the finally block, which will override the value on the stack.

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

Source: https://habr.com/ru/post/950987/


All Articles