String object Clarification required

Let's say I have the following line in my program:

jobSetupErrors.append("abc"); 

In the above case, where jobSetupErrors is StringBuilder (), I see what happens:

  • A new String object is created and set to "abc"
  • the value of this String object is assigned to an existing StringBuilder object

If this is correct and I will add another line ...

 jobSetupErrors.append("abc"); logger.info("abc"); 

In the above example, we create a String object separately 2 times?

If so, would it be more appropriate to do something like this?

 String a = "abc"; jobSetupErrors.append(a); logger.info(a); 

Is this a better approach? Please inform

+4
source share
2 answers

To help figure out, I wrote the class as follows:

 class Test { String a = "abc" ; StringBuilder buffer = new StringBuilder() ; public void normal() { buffer.append( "abc" ) ; buffer.append( "abc" ) ; } public void clever() { buffer.append( a ) ; buffer.append( a ) ; } } 

If we compile this, then run javap on it to extract the bytecode:

 14:09:58 :: javap $ javap -c Test Compiled from "Test.java" class Test extends java.lang.Object{ java.lang.String a; java.lang.StringBuilder buffer; Test(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: aload_0 5: ldc #2; //String abc 7: putfield #3; //Field a:Ljava/lang/String; 10: aload_0 11: new #4; //class java/lang/StringBuilder 14: dup 15: invokespecial #5; //Method java/lang/StringBuilder."<init>":()V 18: putfield #6; //Field buffer:Ljava/lang/StringBuilder; 21: return public void normal(); Code: 0: aload_0 1: getfield #6; //Field buffer:Ljava/lang/StringBuilder; 4: ldc #2; //String abc 6: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 9: pop 10: aload_0 11: getfield #6; //Field buffer:Ljava/lang/StringBuilder; 14: ldc #2; //String abc 16: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: pop 20: return public void clever(); Code: 0: aload_0 1: getfield #6; //Field buffer:Ljava/lang/StringBuilder; 4: aload_0 5: getfield #3; //Field a:Ljava/lang/String; 8: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 11: pop 12: aload_0 13: getfield #6; //Field buffer:Ljava/lang/StringBuilder; 16: aload_0 17: getfield #3; //Field a:Ljava/lang/String; 20: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 23: pop 24: return } 

We can see 2 things.

Firstly, the normal method uses the same String instance for both of these calls (indeed, it is the same literal that is set to the member variable a this class in the initialization block)

And secondly, the clever method clever longer than normal . This is because additional steps are required to retrieve a property from the class.

So, the moral of this story is that in 99% of cases Java does everything right, and there is no need to try to be smart ;-) (and javap is a really cool tool when you want to know exactly what is going on)

+4
source

In the above example, we create a String object separately 2 times?

No, because in Java, string literals (anything in double quotes) are interned. This means that both of these lines belong to the same String , so further optimization is not required.

In your second example, you create an additional reference to the same String , but this is what Java has already done for you by placing a link to it in what is called a string pool. This happens the first time he sees "abc"; the second time, it checks the pool and finds that "abc" already exists, so it is replaced with the same link as the first.

See http://en.wikipedia.org/wiki/String_interning for more information on string interpolation.

+8
source

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


All Articles