最近在求职面试中,我被问到以下问题(针对Java):
假设:
String s1 = "abc";
String s2 = "abc";
的返回值是多少
(s1 == s2)
我回答它会返回false,因为它们是两个不同的对象,==是内存地址比较而不是值比较,并且需要使用.equals()来比较String对象。然而,我被告知虽然.equals(0方法是正确的,但声明仍然是真的。我想知道是否有人可以向我解释为什么它是真的,但为什么我们仍然在学校教授使用equals() ?
答案 0 :(得分:8)
字符串常量由您的JVM 实施(这是规范要求here):
所有文字字符串和字符串值常量表达式都是实体。字符串文字在Java Language Specification
的§3.10.5中定义
这意味着编译器已经创建了一个表示字符串"abc"
的对象,并将s1
和s2
都设置为指向相同的实习对象。
答案 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编译器注意到您在同一程序中多次使用相同的字符串文字时,它不会在内存中多次创建相同的字符串。相反,示例中的s1
和s2
都指向相同的内存。这称为字符串实习。
这就是为什么==
在这种情况下会返回true的原因。但是,如果您从文件或用户输入中读取s2
,则字符串不会自动实现。所以现在它不再指向相同的记忆。因此==
将返回false,而equals
将返回true。这就是为什么你不应该使用==
。
答案 5 :(得分:0)
快速而肮脏的回答:Java优化字符串,因此如果它遇到相同的字符串两次,它将重用相同的对象(这是安全的,因为String是不可变的)。
但是,没有保证。
经常发生的事情是它长时间工作,然后你得到一个令人讨厌的错误,需要永远弄明白,因为有人改变了类加载上下文,你的==不再有效。
答案 6 :(得分:0)
在测试字符串相等性时,您应该继续使用equals()。 Java不保证字符串的身份测试,除非它们被实现。 你的例子中s1 == s2的原因是因为编译器只是在它可以预测的范围内优化2个文字引用。