Java 使用+;操作人员

Java 使用+;操作人员,java,string,memory,memory-management,heap,Java,String,Memory,Memory Management,Heap,String a=“abc” String b=“xyz” 字符串结果=a+b 我想知道“result”字符串是字符串池中分配的字符串常量内存还是在堆上创建的新对象 我知道new String()在堆上创建对象,并在permgen字符串池空间中创建字符串常量,如上面示例中的a、b。如果编译和反编译代码,它将给出以下结果: String result = new StringBuilder().append(a).append(b).toString(); 连接导致分配StringBuilder

String a=“abc”
String b=“xyz”
字符串结果=a+b

我想知道“result”字符串是字符串池中分配的字符串常量内存还是在堆上创建的新对象


我知道new String()在堆上创建对象,并在permgen字符串池空间中创建字符串常量,如上面示例中的a、b。

如果编译和反编译代码,它将给出以下结果:

String result = new StringBuilder().append(a).append(b).toString();

连接导致分配StringBuilder来创建连接的字符串

资料来源:

public class Hello {

    public static final String CONST1 = "cafe";
    public static final String CONST2 = "babe";

    public static void main(String[] args){
        String a = "abc";
        String b = "xyz";
        String result = a + b;

        String result2 = CONST1 + CONST2;
    }
}
通过javap进行反汇编:

public class Hello extends java.lang.Object{
public static final java.lang.String CONST1;

public static final java.lang.String CONST2;

public Hello();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   ldc     #2; //String abc
   2:   astore_1
   3:   ldc     #3; //String xyz
   5:   astore_2
   6:   new     #4; //class java/lang/StringBuilder
   9:   dup
   10:  invokespecial   #5; //Method java/lang/StringBuilder."<init>":()V
   13:  aload_1
   14:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   17:  aload_2
   18:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   21:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   24:  astore_3
   25:  ldc     #8; //String cafebabe
   27:  astore  4
   29:  return

}
公共类Hello扩展了java.lang.Object{
公共静态final java.lang.String常量1;
公共静态final java.lang.String常量2;
公众你好();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:返回
公共静态void main(java.lang.String[]);
代码:
0:ldc#2;//字符串abc
2:astore_1
3:ldc#3;//字符串xyz
5:astore_2
6:new#4;//类java/lang/StringBuilder
9:dup
10:invokespecial#5;//方法java/lang/StringBuilder。”“:()V
13:aload_1
14:invokevirtual#6;//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17:aload_2
18:invokevirtual#6;//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21:invokevirtual#7;//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
24:astore_3
25:ldc#8;//字符串cafebabe
27:astore 4
29:返回
}
您可以在第10行看到用于连接字符串
a
b
StringBuilder
分配。请注意,CONST1和CONST2的串联由编译器在第25行处理。因此,如果字符串是
final
,则不会导致
StringBuilder
分配

一个重要注意事项:

String a = "abc";
String b = "xyz";
String result = a + b;

// creates a number of objects.
String result = new StringBuilder().append(a).append(b).toString();
String result = "abcxyz"; // creates no new objects.
但是

// creates a number of objects.
String result = new StringBuilder().append(a).append(b).toString();
String result = "abcxyz"; // creates no new objects.

result==“abcxyz”返回什么?这应该给你一个关于答案的提示。换句话说,因为变量是
final
,所以它可以被优化,而且Java编译器足够聪明,可以在编译时进行串联。正确,这是
javac
执行的少数优化之一。第一个示例可能会在每次运行时创建3-5个对象,第二个示例不会创建任何对象。但是如果我想动态地使用a+b(之前不知道a和b的值),那么它确实会创建很多对象(由StringBuilder()创建),如果在循环中使用,情况会更糟。如果您只想连接两个字符串,那么使用concat()会稍微高效一些,因为它不会创建StringBuilder。对于所有其他情况(甚至连三个字符串),使用
+
是相当有效的
String x=“xyz”
字符串结果=s.intern()+x.intern()考虑按以下方式使用它,但我认为如果我全面这样做的话,这只会占用permgen空间