当前位置: 首页 > 面试题库 >

Java中字符串连接时为“ ==”

申屠锦
2023-03-14
问题内容

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

ab 都指向字符串常量池中的同一String Literal。所以true在情况1

String d = "dev" + "ender";

应该在内部使用类似-

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

ad 如何指向同一参考而不是 ae


问题答案:

发生了四件事:

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

  2. 相同类中的等效字符串常量(根据JLS中的各种规则,编译器知道的字符串是常量)由编译器(它也在类的“常量池”中列出)引用相同的字符串。这就是为什么a == b

  3. 当类被加载,它的每一个字符串常量自动 扣留 - JVM的字符串池检查等效字符串,如果找到一个,即String使用对象(如果没有,新String的恒新对象添加到池)。因此,即使x是在类中初始化的字符串常量Foo和在类中初始化y的字符串常量Bar,它们也将==彼此存在。

JLS§3.10.5部分覆盖了以上第2点和第3点。(关于类常量池的一点是实现细节,因此是到JVM规范的链接;
JLS只是讲到了内部。)

  1. 编译器在处理常量值时会进行字符串连接,因此
    String d = "dev" + "ender";
    

编译为

    String d = "devender";

并且"devender"是一个字符串常量,编译器和JVM将上面的第2点和第3点应用于该常量。例如,不StringBuilder使用,则串联发生在
编译时 ,而不是运行时。JLS§15.28-
常量表达式
中对此进行了介绍。所以a == d是真正出于同样的原因a == b是正确的:它们指向同一个常量字符串,所以编译器确保他们指的在类的常量池相同的字符串。

当任何一个操作数都不是常量时,编译器将无法执行此操作,因此它不能使用以下操作:

    String e = c + "ender";

…即使代码分析可以很容易地显示出的价值c肯定是"dev",因此e也肯定是"devender"。具体来说,该规范仅允许编译器使用常量值进行连接。因此,由于编译器无法执行此操作,因此它将输出StringBuilder您引用的代码,并且工作在运行时完成,从而创建了一个新String对象。该字符串不会自动e插入,因此最终会指向与该String对象不同的对象a,因此a == e为false。

请注意,如Vinod所说,如果您声明cfinal

    final String c = "dev";

然后它将是一个
常量变量
(是的,它们确实被称为该
变量
),因此将应用§15.28,并且编译器将打开

    String e = c + "ender";

进入

    String e = "devender";

并且a == e也将是如此。

只是重申一下:这都不意味着我们应该使用==比较字符串的等效性。:-)那equals是为了什么。



 类似资料:
  • 问题内容: 为什么在这些情况下输出不同? ==> 印刷:2010年 ==> 打印:200 为什么第一个输出不是30?它与运算符优先级有关吗?就像首先将“ printing”和x连接在一起,然后将结果字符串和y连接在一起?我对么? 问题答案: 它的规则 我在下面显示从高到低的优先顺序: **如果运算符具有相同的优先级 ,* 则 此方法起作用 * 现在 :是字符串” :是Java中唯一将Number连

  • 问题内容: 问题1 在第一种情况下,我知道这是两个字符串文字的串联,因此将对结果“ I Love Java”进行检查,使结果为true。但是,我不确定第二种情况。 问题2 上面的返回false,但是如果我注释掉第1行和第2行,则返回true。这是为什么? 问题答案: 问题的第一部分很简单:Java编译器将多个字符串文字的串联视为一个字符串文字,即 和 是两个完全相同的字符串文字,可以正确地进行in

  • 本文向大家介绍字符串连接的Java程序。,包括了字符串连接的Java程序。的使用技巧和注意事项,需要的朋友参考一下 String类的 concat()方法将指定的字符串连接到该字符串的末尾。 示例 输出结果

  • 问题内容: 我有以下代码 输出为。 Java如何完成字符串连接的技巧? 问题答案: 因为Java将表达式转换为类似 实际上,我认为它可能使用s,因此: 解决更高效 这使用“ 字符串”构建器上的方法(针对每种类型),这些方法可以正确处理

  • 本文章将介绍Thymeleaf标准表达式语法中的概念。 学习如何在Thymeleaf模板中显示对象(Bean)的属性值。 已经将类的bean已经设置为名称为的上下文模型。 为这些和属性添加一些格式,学习使用字符串相连接输出。 最后,修改模板以获得一个合理的静态原型(例如,通过一些原型数据替换并显示结果)。 如果要上机实践,请参考:Thymeleaf+SpringMVC5示例项目。这里不再重复创建项

  • 我正在读一本书叫做。NET Gotchas(非常值得一读),它说明了String和StringBuilder之间的性能差异,它提出了一个我觉得不能没有答案的问题!虽然我不知道这两个类的内部结构(不看这些类的反射版本),但我想知道;因为运算符在。NET是可重载的,为什么微软没有实现String类来在内部使用StringBuilder并重载连接运算符来简单调用。在StringBuilder中追加()?