class StringTest1
{
public static final void main(String... a)
{
String str1="JAVA";
String str2="WORLD";
String str3=str1+str2;
}
}
在此过程中将创建多少个对象? 我想会创建3个对象。
class StringTest2
{
public static final void main(String... a)
{
String strTest="JAVA"+"WORLD";
}
}
在此过程中将创建多少个对象?可以访问多少个对象? 有人告诉我“JAVA”+“WORLD”是一个表达式,它不会存储在字符串池中。
答案 0 :(得分:5)
在第一个示例中,您最终会得到三个String
个对象。您实际上可以在字节码中看到这一点。
假设您有以下代码:
public class StrTest {
public static void main(String[] args) {
String str1 = "JAVA";
String str2 = "WORLD";
String str3 = str1 + str2;
String strTest = "JAVA" + "WORLD";
}
}
生成的字节码是:
public class StrTest {
public StrTest();
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 JAVA
2: astore_1
3: ldc #3 // String WORLD
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 JAVAWORLD
27: astore 4
29: return
}
您可以看到Java编译器在字符串池中为String
和"JAVA"
创建了两个"WORLD"
实例。要将这两者附加在一起,它会创建一个StringBuilder
实例并附加值。之后,它会在该实例上调用toString()
,从而在其中创建一个新的String
实例,其中包含"JAVAWORLD"
。
在第二种情况下,您最终只得到一个String
实例,因为Java编译器足够聪明,可以看到您基本上拥有的是一个常量,因此它通过评估它来执行一些编译时优化表达式并在包含String
的字符串池中创建一个 "JAVAWORLD"
实例。然后将对该实例的引用分配给strTest
。
关于字符串"JAVA"
,"WORLD"
和"JAVAWORLD"
,这些基本上是实习字符串。由于字符串在Java中是不可变的,因此您只需要对一个唯一实例的一个引用,该实例可以在代码中的多个位置重用。这基本上是一种节省内存的方法。
总结一下:
String
个实例:池中有两个,一个在追加后新构造的实例(还创建了一个StringBuilder
实例来附加两个字符串,总共产生4个对象。 / LI>
答案 1 :(得分:1)
String str1="JAVA";
String str2="WORLD";
String strTest="JAVA"+"WORLD";
这三行中的每一行都将导致创建一个String对象。但如果代码多次生成,它将永远是同一个对象。此外,每个String对象都包含一个char[]
对象,因此从技术上讲,每行有2个对象。
String str3=str1+str2;
假设javac
无法对此进行优化,则会将其编译为
String str3 = new StringBuilder(str1).append(str2).toString();
因此,它不仅会创建一个String,还会创建一个在代码中无法访问的StringBuilder。因此,在最坏的情况下,会创建4个对象:String,StringBuilder和char数组(因为它必须在append
期间调整大小)
答案 2 :(得分:0)
在第一种情况下,编译器无法确定str1
和str2
将具有哪些值,因此它不是常量表达式,因此将在运行时进行评估。将有三个对象(两个来自字符串文字,另一个作为其连接创建)。
在第二种情况下,编译器能够计算结果,因此只有一个对象,就像你写了"JAVAWORLD"
答案 3 :(得分:0)
在第一种情况下,将创建三个对象,并且所有这些对象都可以访问,因为您有对它们的实时引用。
在第二种情况下,如果您正在执行类似
的操作String str1="JAVA";
String str2="WORLD";
String strTest="JAVA"+"WORLD";
然后将会创建三个对象。在创建strTest时,“JAVA”将在String对象池中,因此它不会为此分配内存,而是从池中直接引用。同样对于“WORLD”也是如此。然后将从这两个对象中创建一个新对象,并将其分配给strTest。这里的可访问对象将是3。
但如果您正在做类似
的事情 String strTest="JAVA"+"WORLD";
此处只有一个对象是“JAVAWORLD”。池中有“JAVA”和“WORLD”的引用,但是你无法直接访问它们。正如@Vivin Paliath提到的那样,“JAVA”和“WORLD”将被实习,形成一个新的对象“JAVAWORLD”。因此,只创建了两个对象。
有关String对象池see here
的更多信息希望这有帮助。