以下代码创建了多少个String对象?
String x = new String("xyz");
String y = "abc";
x = x + y;
Run Code Online (Sandbox Code Playgroud)
我访问过许多网站,其中一些人说这行代码创建了3个对象,有些人说它创建了4个.我只是想知道在执行这行代码后创建了多少个对象.
das*_*ght 49
在运行结束时将有四个String对象:
String对应于实习"xyz"字面new String("xyz")String对应于实习"abc"字面String对应于连接"xyz" + "abc"真正的问题是将部分或全部这些对象归因于您的程序.可以合理地声称String您的代码只创建了两个或多达四个s.尽管String总共有四个对象,但对象1和3可能不一定由代码创建,因为它们位于常量池中,因此它们是在代码的直接控制之外创建的.
Ste*_*n C 16
这个答案是纠正一些其他答案所提出的误解:
例如:
但编译器可能会用常量("xyzabc")替换x + y.@Binkan Salaryman
...和String对象4 [对应于串联的String]可以由编译器计算并转换为实习常量.@dasblinkenlight
这是不正确的.该JLS状态如下:
15.18.1.字符串连接运算符+
....
除非表达式是常量表达式(第15.28节),否则新创建String对象(第12.5节).
为了限定为常量表达式,表达式中的变量名必须为:
引用常量变量的简单名称(第6.5.6.1节)(§4.12.4).
其中"常量变量"定义为:
常量变量是基本类型或类型String的最终变量,使用常量表达式(第15.28节)初始化.
在这个例子中,没有x或y有final因此他们不是常数变量.即使它们是final,y 但由于new在初始化中使用了运算符,它仍然不会是一个常量变量.
简而言之,不允许 Java编译器使用内联常量"xyzabc"作为串联表达式的结果.
如果我在最后添加以下声明:
System.out.println(x == "xyzabc");
Run Code Online (Sandbox Code Playgroud)
它将始终打印false...假设编译器符合Java语言规范.
小智 12
看看反编译的类,你会看到一切:)答案应该是:
"xyz"和"abc")仅引用常量池中的位置,因此这些不是由您的代码创建的new String("xyz"))字符串连接由编译器优化并更改为StringBuilder,以便间接创建最后一个字符串
public java.lang.String method();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=3, locals=3, args_size=1
0: new #2 // class java/lang/String
3: dup
4: ldc #3 // String xyz
6: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
9: astore_1
10: ldc #5 // String abc
12: astore_2
13: new #6 // class java/lang/StringBuilder
16: dup
17: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V
20: aload_1
21: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: aload_2
25: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore_1
32: aload_1
33: areturn
Run Code Online (Sandbox Code Playgroud)如果要测试实例,请运行此代码段并查看输出:
import static java.lang.System.identityHashCode;
public class Program {
public static void main(String... args) {
String x = new String("xyz");
String y = "abc";
String z = x + y;
System.out.printf("x: %d | %d\n", identityHashCode(x), identityHashCode(x.intern()));
System.out.printf("y: %d | %d\n", identityHashCode(y), identityHashCode(y.intern()));
System.out.printf("z: %d | %d\n", identityHashCode(z), identityHashCode(z.intern()));
}
}
Run Code Online (Sandbox Code Playgroud)
我使用jdk1.7.0_67输出以下内容:
x:414853995 | 1719175803
y:1405489012 | 1405489012
z:1881191331 | 1881191331
这总共有4个String实例......
答案是4.
正如您使用了new关键字一样,Java将在普通(非池)内存中创建一个新的String对象并x引用它.除此之外,文字"xyz"将被放置在字符串池中,这又是另一个字符串对象.
所以,4个字符串对象是:
如果您的代码是这样的:
String x = "xyz";
String y = "abc";
x = x + y;
Run Code Online (Sandbox Code Playgroud)
然后答案是3.
注意:字符串#4位于非池内存中,因为字符串文字和通过计算常量表达式生成的字符串(请参阅JLS§15.28)是唯一隐式实现的字符串.
资料来源:SCJP Sun认证Java 6程序员(第43页,第6章)
| 归档时间: |
|
| 查看次数: |
7502 次 |
| 最近记录: |