比较对象时使用==

时间:2012-02-26 05:01:21

标签: java

最近在求职面试中,我被问到以下问题(针对Java):

假设:

String s1 = "abc";
String s2 = "abc";

的返回值是多少
(s1 == s2)

我回答它会返回false,因为它们是两个不同的对象,==是内存地址比较而不是值比较,并且需要使用.equals()来比较String对象。然而,我被告知虽然.equals(0方法是正确的,但声明仍然是真的。我想知道是否有人可以向我解释为什么它是真的,但为什么我们仍然在学校教授使用equals() ?

7 个答案:

答案 0 :(得分:8)

字符串常量由您的JVM 实施(这是规范要求here):

  

所有文字字符串和字符串值常量表达式都是实体。字符串文字在Java Language Specification

的§3.10.5中定义

这意味着编译器已经创建了一个表示字符串"abc"的对象,并将s1s2都设置为指向相同的实习对象。

答案 1 :(得分:5)

java将实习两个字符串,因为它们都具有相同的值,只有一个实际的字符串实例将存在于内存中 - 这就是==将返回true的原因 - 两个引用都指向同一个实例。

String interning是一种优化技术,用于最小化必须保存在内存中的字符串实例的数量。作为常量表达式值的字符串文字或字符串被实现,以便共享唯一的实例。想想flyweight pattern

答案 2 :(得分:2)

由于您实际上没有为其中任何一个创建String对象的新实例,因此它们共享相同的内存空间。如果是的话 String s1 = new String("abc"); String s2 = new String("abc"); 结果将是错误的。

答案 3 :(得分:2)

原因是字符串是用Java实现的。字符串实习是一种只存储每个不同字符串值的一个副本的方法,该值是不可变的。实习字符串使一些字符串处理任务更有效。不同的值存储在字符串实习池中。 (来自wiki)

答案 4 :(得分:1)

==使用内存地址是对的。但是,当java编译器注意到您在同一程序中多次使用相同的字符串文字时,它不会在内存中多次创建相同的字符串。相反,示例中的s1s2都指向相同的内存。这称为字符串实习。

这就是为什么==在这种情况下会返回true的原因。但是,如果您从文件或用户输入中读取s2,则字符串不会自动实现。所以现在它不再指向相同的记忆。因此==将返回false,而equals将返回true。这就是为什么你不应该使用==

答案 5 :(得分:0)

快速而肮脏的回答:Java优化字符串,因此如果它遇到相同的字符串两次,它将重用相同的对象(这是安全的,因为String是不可变的)。

但是,没有保证。

经常发生的事情是它长时间工作,然后你得到一个令人讨厌的错误,需要永远弄明白,因为有人改变了类加载上下文,你的==不再有效。

答案 6 :(得分:0)

在测试字符串相等性时,您应该继续使用equals()。 Java不保证字符串的身份测试,除非它们被实现。 你的例子中s1 == s2的原因是因为编译器只是在它可以预测的范围内优化2个文字引用。