字符串文字和字符串对象的添加之间的区别
||
字符串文字和字符串对象的添加有什么区别?
例如
String s1 =\"hello\";
String s2 =\"hello1\";
String s3 =\"hello\" + \"hello1\";
String s4 =\"hellohello1\";
String s5 = s1 + s2;
System.out.println(s3 == s4); // returns true
System.out.println(s3 == s5); // return false
System.out.println(s4 == s5); // return false
为什么s3
/s4
与s5
不在同一位置?
没有找到相关结果
已邀请:
4 个回复
填盖
不是常数表达式,由于
和
不是
,因此其结果不会被求和,即创建另一个对象来表示它,因此引用比较将生成
。 JLS 3.10.5字符串文字: 字符串文字(或更一般而言,为常量表达式的值(第15.28节)的字符串)为“ interned \”,以便使用String.intern方法共享唯一的实例。 JLS 15.28常数表达式: 编译时常量表达式是表示原始类型或String的值的表达式,该值不会突然完成,并且仅使用以下内容组成: ... 引用常量变量的简单名称(第4.12.4节)。 JLS 4.12.4定义了“ 7”个变量。 如果将
和
声明为
,则
将是
。
博沮富教全
。 如果您对引用的比较是有意的,则不清楚为什么您期望编译器/ JVM内收或不内收以不同方式产生的相同字符串。
苛肠倒俱
优化为
,ѭ2也重用了
。我很惊讶该编译器不够聪明,无法对ѭ3进行相同的处理。您正在使用哪个JDK版本?仅对常量表达式允许这种优化(请参阅Java语言规范的15.28)。换句话说,对非最终变量的任何赋值都拒绝了后续优化的可能性。 这是一个简单类的ѭ21的输出,该类将您的代码包装到一个主要方法中(不是有人要它,但我很好奇我自己)。因此,让我们看看发生了什么:
我不是有经验的阅读字节码,但我会努力的:) 以#开头的数字(例如#16)是对常量池的引用。内容总是作为注释添加到此行
后跟
表示“装入常数#16并将其存储在插槽1中”。如您所见,这在插槽1-4的开头执行了4次,转换为s1,s2,s3和s4(请参阅LocalVariableTable)。 对于s5,无需过多说明,显然有一个StringBuilder并加载了插槽1(in25ѭ)和插槽2(
),然后将结果存储在插槽5(
)中。
诫商
但是,这很少需要。