为什么有时候,"=="关系运算符不能代替.equals()方法来比较对象?

mos*_*sir 7 java object

我在一本书中查了一下,这本书在解释方面通常比网站更全面.

以此为例:

if (nickname == "Bob")
Run Code Online (Sandbox Code Playgroud)

仅当nickname引用相同的String对象时,该条件才为真.

这是我发现令人困惑的一句话,任何人都可以解释为什么会这样:

为了提高效率,Java只为每个字符串常量生成一个字符串对象.

该书指出,组装对象"鲍勃"的方式也会影响条件是否真实,这最让我困惑.

例如:

String nickname = "Bob";
...
if (nickname == "Bob") //TRUE
Run Code Online (Sandbox Code Playgroud)

但是如果从.substring()方法创建"Bob" ,则条件将为FALSE.

String name = "Robert";
String nickname = name.substring(0,3);
...
if (nickname == "Rob")//FALSE
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

编辑:在本书的解释结束时,我发现了一句让我困惑的句子:

因为字符串对象总是由编译器构造,所以您永远不会对是否共享两个字符串对象感兴趣.

我们编写的所有内容都不是由编译器构建的吗?

Ser*_*kov 10

你需要了解两件事

1)

String a = "Bob";
String b = "Bob";

System.out.println(a.equals(b));
System.out.println(a == b);
Run Code Online (Sandbox Code Playgroud)

你怎么想?什么输出?

true
true
Run Code Online (Sandbox Code Playgroud)

这是做什么的?在永久生成内存的字符串池中创建的第一个字符串 第二个字符串从池中获取现有对象.

String a = "Bob"; // create object in string pool(perm-gen)
String b = "Bob"; // getting existing object.
Run Code Online (Sandbox Code Playgroud)

你有多注意:

为了提高效率,Java只为每个字符串常量生成一个字符串对象.

2)

String nickname = name.substring(0,3);
Run Code Online (Sandbox Code Playgroud)

因为String是在堆内存中name.substring(0,3);创建的不可变对象,而不是在perm-gen中.new String("Rob")

注意 :

在Java 8中,在Heap的PermGen区域中创建了字符串池,垃圾收集可以在perm空间中进行,但依赖于JVM到JVM.顺便提一下,从JDK 1.7更新,String池被移动到创建对象的堆区域.

在这里阅读更多.

  • ......嗯,Java 8中没有permgen ... (5认同)
  • [什么是字符串文字池?](http://www.xyzws.com/Javafaq/what-is-string-literal-pool/3)适用于不熟悉池的人. (2认同)