当前位置: 首页 > 知识库问答 >
问题:

在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

a

String d = "dev" + "ender";

应该在内部使用类似于:

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

如何一个

共有3个答案

颛孙炜
2023-03-14

de之间的区别在于,当您连接字符串文本时,连接是在编译时执行的。Java编译器以与表达式相同的方式处理表达式,在编译时生成相同的文本。由于所有String文本都被插入,因此d,这是“dev”“ender”的结果,也最终引用了与ab“devender”相同的对象。

e的表达式,即c"ender",在运行时计算。即使它产生相同的字符串,编译器也不会使用这个事实。这就是为什么产生了一个不同的String对象,导致在==上的比较失败。

斜昊空
2023-03-14

编译器在引擎盖下进行了大量优化。

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将在编译期间自行解决。

沃阳飙
2023-03-14

目前有四件事:

>

  • (你很清楚这一点,但对于潜伏者来说)=测试变量是否指向相同的字符串对象,而不是等效的字符串。因此,即使x“foo”并且y也是“foo”x==y可能是真或假,这取决于xy是指相同的字符串对象还是指不同的对象。这就是为什么我们使用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 ?

    • 为什么它抛出一个错误?任何帮助都将不胜感激 编辑: