" =="在Java中使用字符串连接的情况下 [英] "==" in case of String concatenation in Java

查看:88
本文介绍了" =="在Java中使用字符串连接的情况下的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

    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 ,如果是1

a & b both are pointing to the same String Literal in string constant pool. So true in case 1

String d = "dev" + "ender";

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

should be internally using something like -

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

a & d 指向相同的参考&不是 a & e

How a & d are pointing to the same reference & not a & e ?

推荐答案

发生了四件事:


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

  1. (You clearly know this, but for lurkers) == tests to see if the variables point to the same String object, not equivalent strings. So even if x is "foo" and y is also "foo", x == y may be true or false, depending on whether x and y refer to the same String object or different ones. That's why we use equals, not ==, to compare strings for equivalence. All of the following is just meant to explain why == is sometimes true, it's not a suggestion to use == to compare strings. :-)

同一个字符串常量(编译器知道的字符串是根据JLS中的各种规则的常量)在同一个类中被引用来指代相同的编译器的字符串(也在类的常数池)。这就是 a == b 为真的原因。

Equivalent string constants (strings the compiler knows are constants according to various rules in the JLS) within the same class are made to refer to the same string by the compiler (which also lists them in the class's "constant pool"). That's why a == b is true.

当加载类时,每个字符串都是如此常量自动 interned 功能;—检查JVM的字符串池是否有等效字符串,如果找到,则使用 String 对象(如果没有,则使用新的 String 将新常量的对象添加到池中。因此,即使 x 是在类 Foo y 是在类 Bar 中初始化的字符串常量,它们将是 == 彼此。

When the class is loaded, each of its string constants is automatically interned — the JVM's string pool is checked for an equivalent string and if one is found, that String object is used (if not, the new String object for the new constant is added to the pool). So even if x is a string constant initialized in class Foo and y is a string constant initialized in class Bar, they'll be == each other.

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

Points 2 and 3 above are covered in part by JLS§3.10.5. (The bit about the class constant pool is a bit of an implementation detail, hence the link to the JVM spec earlier; the JLS just speaks of interning.)

如果编译器处理常量值,编译器会进行字符串连接,所以

The compiler does string concatenation if it's dealing with constant values, so

String d = "dev" + "ender";

编译为

String d = "devender";

devender是一个字符串常量编译器和JVM将上面的第2点和第3点应用于。例如,没有使用 StringBuilder ,连接发生在编译时,而不是运行时。这包含在JLS§15.28中 - 常量表达式 。所以 a == d 的原因是正确的 a == b 为真:它们引用相同的常量字符串,因此编译器确保它们引用类的常量池中的相同字符串。

and "devender" is a string constant the compiler and JVM apply points 2 and 3 above to. E.g., no StringBuilder is used, the concatenation happens at compile-time, not runtime. This is covered in JLS§15.28 - Constant Expressions. So a == d is true for the same reason a == b is true: They refer to the same constant string, so the compiler ensured they were referring to the same string in the class's constant pool.

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

The compiler can't do that when any of the operands is not a constant, so it can't do that with:

String e = c + "ender";

...即使代码分析可以轻松显示 c的值绝对是dev因此 e 肯定是 devender。规范只让编译器使用常量值进行串联。因此,由于编译器无法执行此操作,因此它会输出您引用的 StringBuilder 代码,并且该工作在运行时完成,从而创建新的 String 对象。该字符串不会自动实现,因此 e 最终会引用与 String 对象> a 确实如此,所以 a == e 为假。

...even though code analysis could easily show that the value of c will definitely be "dev" and thus e will definitely be "devender". The specification only has the compiler do the concatenation with constant values, specifically. So since the compiler can't do it, it outputs the StringBuilder code you referred to and that work is done at runtime, creating a new String object. That string isn't automatically interned, so e ends up referring to a different String object than a does, and so a == e is false.

请注意正如Vinod所说,如果您宣布 c as final

Note that as Vinod said, if you declared c as final:

final String c = "dev";

那么它将是 常量变量 (是的,它们真的叫做那个)§15.28将适用,编译器将转为

Then it would be a constant variable (yes, they're really called that) and so §15.28 would apply and the compiler would turn

String e = c + "ender";

进入

String e = "devender";

a == e 也将是是的。

重申:没有一个意味着我们应该使用 == 比较字符串的等价性。 :-)这就是等于的目的。

Just to reiterate: None of which means we should use == to compare strings for equivalence. :-) That's what equals is for.

这篇关于" =="在Java中使用字符串连接的情况下的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆