下面这两种说法有什么不同?
String s = "text";
String s = new String("text");
下面这两种说法有什么不同?
String s = "text";
String s = new String("text");
当前回答
在字符串字面值池中创建任何字符串字面值,并且池不允许任何副本。因此,如果两个或多个字符串对象初始化为相同的字面值,那么所有对象将指向相同的字面值。
String obj1 = "abc";
String obj2 = "abc";
"obj1"和"obj2"将指向相同的字符串字面量,字符串字面量池将只有一个"abc"字面量。
当我们使用new关键字创建String类对象时,这样创建的字符串存储在堆内存中。任何作为参数传递给string类的构造函数的字符串字面值都存储在字符串池中。如果我们使用new操作符使用相同的值创建多个对象,每次都会在堆中创建一个新对象,因为应该避免使用这个new操作符。
String obj1 = new String("abc");
String obj2 = new String("abc");
"obj1"和"obj2"将指向堆中两个不同的对象,字符串字面量池将只有一个"abc"字面量。
关于字符串的行为还有一点值得注意,那就是任何对字符串进行的赋值或连接都会在内存中创建一个新对象。
String str1 = "abc";
String str2 = "abc" + "def";
str1 = "xyz";
str2 = str1 + "ghi";
在上面的例子中: 第1行:“abc”字面值存储在字符串池中。 第2行:"abcdef"字面值存储在字符串池中。 第3行:一个新的“xyz”字面值存储在字符串池中,“str1”开始指向这个字面值。 第4行:由于该值是通过附加到另一个变量而生成的,因此结果存储在堆内存中,被附加的字面量“ghi”将在字符串池中检查是否存在,并将被创建,因为在上述情况下它不存在。
其他回答
@Braj:我想你已经提到了另一种方式。如果我错了,请指正
逐行创建对象:
字符串 str1 = new String(“java5”)
Pool- "java5" (1 Object)
Heap - str1 => "java5" (1 Object)
String str2 = "java5"
pool- str2 => "java5" (1 Object)
heap - str1 => "java5" (1 Object)
字符串 str3 = 新字符串(str2)
pool- str2 => "java5" (1 Object)
heap- str1 => "java5", str3 => "java5" (2 Objects)
String str4 = "java5"
pool - str2 => str4 => "java5" (1 Object)
heap - str1 => "java5", str3 => "java5" (2 Objects)
一个是在字符串常量池中创建一个字符串
String s = "text";
另一个在常量池中创建一个字符串("text"),在普通堆空间中创建另一个字符串(s)。两个字符串的值相同,即"text"。
String s = new String("text");
如果以后未使用,则会丢失(符合GC的条件)。
另一方面,字符串字面值被重用。如果你在你的类的多个地方使用“text”,它实际上将是一个且只有一个String(即在池中多次引用同一个字符串)。
一个简单的理解差异的方法如下:-
String s ="abc";
String s1= "abc";
String s2=new String("abc");
if(s==s1){
System.out.println("s==s1 is true");
}else{
System.out.println("s==s1 is false");
}
if(s==s2){
System.out.println("s==s2 is true");
}else{
System.out.println("s==s2 is false");
}
输出是
s==s1 is true
s==s2 is false
因此new String()总是会创建一个新实例。
字符串字面值将进入字符串常量池。
下面的快照可能会帮助你从视觉上理解它,从而更长时间地记住它。
逐行创建对象:
String str1 = new String("java5");
在构造函数中使用字符串字面值“java5”,新的字符串值存储在字符串常量池中。 使用new操作符,在堆中创建一个以“java5”为值的新字符串对象。
String str2 = "java5"
引用“str2”指向字符串常量池中已经存储的值
String str3 = new String(str2);
在堆中创建一个新的字符串对象,其值与"str2"引用的值相同。
String str4 = "java5";
引用“str4”指向字符串常量池中已经存储的值
对象总数:堆- 2,池- 1
Oracle社区的进一步阅读
把“bla”想象成一个魔法工厂,就像Strings.createString(“bla”)(pseudo)。工厂保存了所有以这种方式创建的字符串池。
如果它被调用,它会检查池中是否已经有这个值的字符串。如果为真,则返回此string对象,因此以这种方式获得的字符串确实是同一个对象。
如果不是,它在内部创建一个新的字符串对象,将其保存在池中,然后返回它。因此,当下次查询相同的字符串值时,它将返回相同的实例。
手动创建新的String("")通过绕过字符串字面量池来覆盖这种行为。因此,应该始终使用equals()检查相等性,它比较字符序列,而不是对象引用相等性。