String a = "devender";
String b = "devender";
String c = "dev";
String d = "dev" + "ender";
String e = c + "ender";
System.out.println(a == b); //case 1: o/p true
System.out.println(a == d); //case 2: o/p true
System.out.println(a == e); //case 3: o/p false
a
String d = "dev" + "ender";
应该在内部使用类似于:
String d = new StringBuilder().append("dev").append("ender").toString();
如何一个
d
和e
之间的区别在于,当您连接字符串文本时,连接是在编译时执行的。Java编译器以与表达式相同的方式处理表达式,在编译时生成相同的文本。由于所有String
文本都被插入,因此d
,这是“dev”“ender”
的结果,也最终引用了与a
和b
的“devender”
相同的对象。
e
的表达式,即c"ender"
,在运行时计算。即使它产生相同的字符串,编译器也不会使用这个事实。这就是为什么产生了一个不同的String
对象,导致在==
上的比较失败。
编译器在引擎盖下进行了大量优化。
String d = "dev" + "ender";
在编译程序时,编译器会将dev"ender"
替换为"devender"
。如果要添加2个字面值(这既适用于原语,也适用于Strings),编译器将执行此优化。
Java代码:
String d = "dev" + "ender";
字节码:
0: ldc #16 // String devender
谈到一个特例:
final String c = "dev"; // mark this as final
String e = c + "ender";
使c
最终将使String成为编译时常量。编译器将意识到c
的值不能改变,因此将在编译时用"dev"值替换c
的所有出现,因此e
将在编译期间自行解决。
目前有四件事:
>
(你很清楚这一点,但对于潜伏者来说)=
测试变量是否指向相同的字符串
对象,而不是等效的字符串。因此,即使x
是“foo”
并且y
也是“foo”
,x==y
可能是真或假,这取决于x
和y
是指相同的字符串对象还是指不同的对象。这就是为什么我们使用
equals
,而不是=
,来比较字符串的等价性。以下所有内容只是为了解释为什么=
有时是正确的,并不建议使用=
来比较字符串。:-)
同一类中的等效字符串常量(编译器知道的字符串是符合JLS中各种规则的常量)由编译器引用同一字符串(编译器还将它们列在类的“常量池”中)。这就是为什么
a==b
是正确的。
当类被加载时,它的每个字符串常量都会被自动插入
JLS§3.10部分涵盖了上述第2点和第3点。5.(关于类常量池的部分是一个实现细节,因此前面有到JVM规范的链接;JLS只提到了interning。)
如果编译器处理的是常量值,它会进行字符串连接,因此
String d = "dev" + "ender";
被编译成
String d = "devender";
而
“devender”
是编译器和JVM应用上述第2点和第3点的字符串常量。例如,如果不使用StringBuilder
,则连接发生在编译时,而不是运行时。这在JLS§15.28-常量表达式中有说明。因此a==d
为true,原因与a==b
为true相同:它们引用相同的常量字符串,因此编译器确保它们引用的是类的常量池中的相同字符串。
当任何操作数不是常量时,编译器都无法执行此操作,因此在以下情况下无法执行此操作:
String e = c + "ender";
...即使代码分析可以很容易地表明
c
的值肯定是“dev”
,因此e
肯定是“devender”
。该规范只让编译器使用常量值进行连接,具体来说。因此,由于编译器无法执行此操作,它将输出您提到的StringBuilder
代码,并且该工作将在运行时完成,从而创建一个新的String
对象。该字符串不会自动插入,因此e
最终引用的string
对象与a
不同,因此a==e
为false。
请注意,正如Vinod所说,如果您将
c
声明为最终
:
final String c = "dev";
然后它将是一个常量变量(是的,它们实际上被称为常量变量),因此§15.28将被应用,编译器将
String e = c + "ender";
成
String e = "devender";
而且
a==e
也是正确的。
只是重申一下:这些都不意味着我们应该使用
==
来比较字符串的等价性。:-)这就是equals
的目的。
问题内容: 用Java有没有更优雅的方法? 是否可以将变量直接放在字符串中并对其值求值? 问题答案: String test = String.format(“test goes here %s more text”, “Testing”); 是您可以用Java写的最接近的东西
问题内容: 我需要在检查的同时将以下更改为- ,以改善圈复杂度。 但是我不确定我将获得什么价值。 问题答案: Java(版本7之前的版本)在switch / case中不支持String。但是您可以通过使用枚举来达到预期的结果。
问题内容: 我在何时遇到oracle的问题。 该查询始终返回null,尽管很明显结果应该是第一种情况。我是否缺少有关oracle中字符串比较的内容? 问题答案: 您要再次检查字符串和一个空字符串,从而出现问题;在Oracle中,您最好检查一下您的字符串: 关于Oracle处理空字符串和空值的方式,在这里您可以找到更多信息 一个例子: 给出: 简而言之,谈论时,您可以依靠的唯一支票是:
我是第一次使用代码优先的方法。如果我错过了一些非常基本的东西,请原谅我。 我需要传递连接字符串到DB上下文,但我不能将连接字符串app.config,因为我在类本身调用一个金块,它给我连接字符串。 这种做法正确吗?我无法在本地系统上测试此功能。还是我应该把绳子传给基地 类A():基(连接)
问题内容: String a = “devender”; String b = “devender”; String c = “dev”; String d = “dev” + “ender”; String e = c + “ender”; a 和 b 都指向字符串常量池中的同一String Literal。所以在情况1 应该在内部使用类似- a 和 d 如何指向同一参考而不是 a & e ?
为什么它抛出一个错误?任何帮助都将不胜感激 编辑: