字符串池对象

Kum*_*mar 4 java string

能否请您澄清一下,在下面的案例中会创建多少个对象?为什么?我对此略感不安.

String s1 = "cat";

String s2 = "cat";

String s3 = "c"+"at";

String s4 = new String("cat");

String s5 = "kitty"+"cat";

String s6 = new String("kittycat");

String s7 = s5;

String s8= new String(s5); // Newly Added in this Question
Run Code Online (Sandbox Code Playgroud)

Tag*_*eev 8

让我们一步一步看:

String s1 = "cat";
String s2 = "cat";
Run Code Online (Sandbox Code Playgroud)

这两个将是javac编译器在类文件中创建的相同常量池条目.加载此类时,此字符串(以及所有其他常量池字符串)将自动实现,因此它也将与"cat"其他类中的其他字符串合并.

String s3 = "c"+"at";
Run Code Online (Sandbox Code Playgroud)

这实际上是相同的:如果在编译期间可以计算字符串连接,则由javac完成.所以它s1和and 几乎一样s2.这由JLS 第15.18.1章涵盖:

除非表达式是常量表达式(第15.28节),否则新创建String对象(第12.5节).

String s4 = new String("cat");
Run Code Online (Sandbox Code Playgroud)

在这里,您明确地创建一个新对象.Java语言保证在使用new关键字时,您将拥有一个新的不同对象,该对象不能与先前创建的任何对象相同.但是,如果仅在当前方法中使用此对象(或者在可以内联到当前方法中的方法中)并且不使用==操作将其与其他字符串进行比较,则JIT编译器可以跳过对象分配以进行优化.但是如果你实际使用==or System.identityHashCode,或者这个方法是作为解释帧执行的,那么它实际上就是新对象.

"cat"被传递到的参数串实际是相同的对象s1,s2s3.

String s5 = "kitty"+"cat";
Run Code Online (Sandbox Code Playgroud)

这类似于s3:javac编译器只会"kittycat"在编译期间创建一个字符串.查看字节码,您甚至无法知道源中存在串联.

String s6 = new String("kittycat");
Run Code Online (Sandbox Code Playgroud)

这类似于s4:显式创建新对象.如果您稍后尝试使用s6 == "kittycat",您将获得false.

String s7 = s5;
Run Code Online (Sandbox Code Playgroud)

在这里,您只需为先前创建的s5字符串分配引用,因此此处不会创建新对象.

所以答案是:最多会创建4个字符串,但在某些情况下,它可以优化到2个字符串.最重要的是:如果你试图检查同一个程序中有多少个字符串(即不使用Java代理或分析内存转储),你将总是得到四个.

  • 所以我的回答2收到主要的下降并不是错误的,事实上这个问题是正确的:). (2认同)