java - "=="在 Java 中字符串连接的情况下

标签 java string

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 & b 都指向字符串常量池中的同一个字符串字面量。所以 true in case 1

String d = "dev" + "ender";

应该在内部使用类似的东西:

String d = new StringBuilder().append("dev").append("ender").toString();

ad 如何指向同一个引用而不是 ae

最佳答案

正在发生四件事:

  1. (你清楚地知道这一点,但对于潜伏者)== 测试变量是否指向相同的String 对象,而不是等效字符串。所以即使 x"foo" 并且 y 也是 "foo", x == y 可能是 true 或 false,这取决于 xy 是指相同的 String 对象还是不同的对象。这就是我们使用 equals 的原因。 ,而不是 ==,来比较字符串是否相等。以下所有内容只是为了解释为什么 == 有时为真,不建议使用 == 来比较字符串。 :-)

  2. 同一个类中的等价字符串常量(编译器知道的字符串是根据 JLS 中的各种规则的常量)由编译器引用同一个字符串(它也在类的 "constant pool" 中列出了它们) )。这就是 a == b 为真的原因。

  3. 加载类时,其每个字符串常量自动为interned — 检查 JVM 的字符串池中是否存在等效字符串,如果找到,则使用该 String 对象(如果没有,则添加新常量的新 String 对象到游泳池)。所以即使 x 是在类 Foo 中初始化的字符串常量,而 y 是在类 Bar 中初始化的字符串常量,它们将是 == 彼此。

    以上第 2 点和第 3 点已被 JLS§3.10.5 部分覆盖。 . (关于类常量池的部分是一个实现细节,因此链接到前面的 JVM 规范;JLS 只是谈到实习。)

  4. 编译器在处理常量值时会进行字符串连接,所以

    String d = "dev" + "ender";
    

    编译成

    String d = "devender";
    

    and "devender" 是一个字符串常量,编译器和 JVM 将上面的第 2 点和第 3 点应用到。例如,没有使用 StringBuilder,连接发生在 compile-time,而不是运行时。这在 JLS§15.28 - Constant Expressions 中有介绍.所以 a == d 为 true 的原因与 a == b 为 true 的原因相同:它们引用相同的常量字符串,因此编译器确保它们引用的是相同的类常量池中的字符串。

    当任何操作数不是常量时,编译器不能这样做,所以它不能这样做:

    String e = c + "ender";
    

    ...即使代码分析很容易表明 c 的值肯定是 "dev" 并且因此 e 肯定会是“开发者”。具体来说,规范只让编译器与常量值进行连接。因此,由于编译器无法执行此操作,它会输出您引用的 StringBuilder 代码,并且该工作在运行时完成,创建一个新的 String 对象。该字符串不会自动被保留,因此 e 最终会引用与 a 不同的 String 对象,因此 a = = e 为假。

    请注意 as Vinod said , 如果您将 c 声明为 final:

    final String c = "dev";
    

    那么它将是 constant variable (是的,它们确实被称为),因此 §15.28 将适用,编译器将转向

    String e = c + "ender";
    

    进入

    String e = "devender";
    

    a == e 也是如此。

重申一下:这些都不意味着我们应该使用 == 来比较字符串的等价性。 :-) 这就是 equals 的用途。

关于java - "=="在 Java 中字符串连接的情况下,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34509566/

相关文章:

java - JAXB 编码(marshal) setProperty com.sun.xml.bind.CharacterEscapeHandler

java - 导出的 jar 文件不播放声音

java - 无法获取文本字段中的文本输入以解析为双倍

ios - 匹配字符串模式,包括 Swift 中的变量部分

c# - 允许搜索重音字符吗?

java - 唤醒线程而不会有被阻塞的风险

java - 将 XML 序列化转换回 Java 代码

python - 如何显示列表中字符串的重复项

c - strtol() 和 atol() 不转换大于 9 位的字符串

java - 这是使用验证功能扩展所有 Java Swing GUI 的正确方法吗