下面这两种说法有什么不同?

String s = "text";

String s = new String("text");

当前回答

字符串字面值将进入字符串常量池。

下面的快照可能会帮助你从视觉上理解它,从而更长时间地记住它。


逐行创建对象:

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社区的进一步阅读

其他回答

@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 str = new String("hello")

它将检查字符串常量池是否已经包含字符串“hello”? 如果存在,则不会在String常量池中添加条目。如果不存在,它将在String常量池中添加一个条目。

对象将在堆内存区域中创建,str引用指向在堆内存位置中创建的对象。

如果你想要str引用String常量池中包含的点对象,则必须显式调用str.intern();

String str = "world";

它将检查字符串常量池是否已经包含字符串“hello”? 如果存在,则不会在String常量池中添加条目。如果不存在,它将在String常量池中添加一个条目。

在上述两种情况下,str引用指向常量池中存在的字符串“world”。

字符串字面值将进入字符串常量池。

下面的快照可能会帮助你从视觉上理解它,从而更长时间地记住它。


逐行创建对象:

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()检查相等性,它比较字符序列,而不是对象引用相等性。