分配并创建新的字符串差异

时间:2013-04-13 09:13:14

标签: java string

        String s1 = new String("string");
        String s2 = new String("string");

        String s3 = "string";
        String s4 = "string";

        System.out.println(s1 == s2);      //FALSE
        System.out.println(s2.equals(s1)); //TRUE

        System.out.println(s3 == s4);      //TRUE
        System.out.println(s3.equals(s4)); //TRUE

创建s1s3 之间有什么区别? 请让我知道

在String中我们只有String对象,那么为什么它以不同的方式处理这两个。 s1和s2具有不同的存储器地址,而s3和s4具有相同的存储器地址。 为什么它基于 new 运算符。?

4 个答案:

答案 0 :(得分:5)

当加载定义它们的类时,Java源代码中表示字符串文字的String对象将添加到共享String池中。这确保了String文字的所有“副本”实际上都是同一个对象......即使文字出现在多个类中。这就是为什么s3 == s4true

相反,当您new一个String时,会创建一个不同的新String对象。这就是s1 == s2false的原因。 (这是new的基本属性。保证创建并返回一个新对象......如果它正常完成。)

但是,在任何一种情况下,字符串都会使用相同的字符,这就是equals返回true的原因。


虽然理解正在发生的事情很重要,但真正的课程是正确的比较Java字符串的方法是使用equals而不是==

如果要安排使用==测试String对象的相等性,可以使用String.intern方法“实例化”它们。但是,你必须始终这样做......并且实习在各方面都是一个昂贵的过程......因此通常不是一个好主意。

答案 1 :(得分:3)

s1是一个新的String对象,不属于任何池化实例的一部分。 s3是来自池的字符串实例。查找 java String pool 。请查看String上的相关intern()方法。

这个概念并不是java独有的。其他语言支持String interning。在该相关说明中,池化经常使用的对象遵循flyweight模式,并且不限于字符串。看看Integer.valueOf()。整数也有自己的恒定池。

答案 2 :(得分:2)

JVM具有自动优化功能。除非您专门创建一个新的String对象,并且另一个String对象已经存在且具有相同的值,否则JVM会自动认为新对象不是必需的,并且会为您分配一个指向已存在的相等String对象的指针。

基本上,当你使用第二个选项时,会发生这种情况:

第1步

创建第一个对象没问题。

第2步

在创建第二个对象之前,将检查字符串池的值。 如果该值当前存在,则无需创建新对象。它只返回对String对象的引用。

第3步

不是分配新的Object,而是简单地给出对步骤1中对象的引用。这是为了节省内存。

答案 3 :(得分:0)

这是因为new运算符强制创建一个新的String实例,而在第二种情况下,因为String是一个不可变类,JVM为你提供了相同的String实例变量来节省内存。因为其中一个这样的对象不会发生变化而导致第二个变化(不可变,记得吗?)这是可以的。