当前位置:  开发笔记 > 编程语言 > 正文

"=="用于Java中的字符串连接

如何解决《"=="用于Java中的字符串连接》经验,为你挑选了6个好方法。

有四件事情在发生:

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

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

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

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

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

    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也是错误的.

    需要注意的是为维诺德说,如果声明cfinal:

    final String c = "dev";
    

    然后它将是一个常量变量(是的,它们真的被称为),因此§15.28将适用并且编译器将转向

    String e = c + "ender";
    

    String e = "devender";
    

    而且a == e也是如此.

重申一下:没有一个意味着我们应该==用来比较字符串的等价性.:-)这equals就是为了什么.



1> T.J. Crowder..:

有四件事情在发生:

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

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

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

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

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

    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也是错误的.

    需要注意的是为维诺德说,如果声明cfinal:

    final String c = "dev";
    

    然后它将是一个常量变量(是的,它们真的被称为),因此§15.28将适用并且编译器将转向

    String e = c + "ender";
    

    String e = "devender";
    

    而且a == e也是如此.

重申一下:没有一个意味着我们应该==用来比较字符串的等价性.:-)这equals就是为了什么.



2> TheLostMind..:

编译器在幕后进行了大量优化.

String d = "dev" + "ender";

在这里,编译器将取代"dev" + "ender""devender"被编译的程序时.如果要添加2个文字(这适用于基元和字符串),编译器会执行此优化.

Java代码:

String d = "dev" + "ender";

字节代码:

  0: ldc           #16                 // String devender

来到一个特例:

final String c = "dev"; // mark this as final
String e = c + "ender";

使cfinal成为String的编译时常量.编译器将意识到值c不能改变,因此在编译时c用值"dev" 替换所有出现的值,因此e将在编译期间自行解决.



3> Davide Loren..:

正如你在内部所说,最后的连接是针对类似的东西完成的

String e = new StringBuilder().append(c).append("ender").toString();

实施toString()StringBuilder 创建一个新字符串.这是实施.

public String toString() {
     // Create a copy, don't share the array
     return new String(value, 0, count);
}

仅当两个字符串相同时才使用==而不是.equals() 返回true来比较字符串.在这种情况下,它们不相同,因为第二个字符串是作为类型的新对象创建String.

其他连接由编译器直接执行,因此不会创建新的String.



4> Bathsheba..:

"dev" + "ender"是一个编译时可计算的常量表达式:两个参数都是字符串文字.因此,表达是"devender".

同样不能说c + "ender":某些情况(某些代码在不同的线程上运行)可能导致c设置为不同的值.符合条件c是为了final避免这种可能性,在这种情况下e也会引用相同的对象a.

所以a,bd所有引用同一个对象.



5> dasblinkenli..:

d和之间的区别在于e,当您连接字符串文字时,连接是在编译时执行的.Java编译器"dev" + "ender"以与"devender"表达式相同的方式处理表达式,在编译时生成相同的文字.由于所有String文字得到实习,d,这是一个结果"dev" + "ender",也结束了引用相同的对象ab"devender".

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



6> 小智..:

字符串d ="dev"+"ender"; 常数+常数,'d'仍然是常数(同一个),所以(a == d)为真;

字符串e = c +"ender"; 变量+常量,结果'e'是一个变量,它将在内部使用StringBuilder,并创建一个新的引用.

推荐阅读
有风吹过best
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有