我想知道在我的Java代码中什么情况下需要使用字符串对象。好的,我理解了字符串字面量和字符串对象之间的区别,但是我想知道既然Java赋予我们创建字符串对象的能力,肯定有一些原因,在某些情况下创建字符串对象会很有用。因此,我想知道在哪种情况下我们可以优先选择使用字符串对象而不是字符串字面量。
我想知道在我的Java代码中什么情况下需要使用字符串对象。好的,我理解了字符串字面量和字符串对象之间的区别,但是我想知道既然Java赋予我们创建字符串对象的能力,肯定有一些原因,在某些情况下创建字符串对象会很有用。因此,我想知道在哪种情况下我们可以优先选择使用字符串对象而不是字符串字面量。
Item 5: Avoid creating unnecessary objects
It is often appropriate to reuse a single object instead of creating a new functionally equivalent object each time it is needed. Reuse can be both faster and more stylish. An object can always be reused if it is immutable (Item 15). As an extreme example of what not to do, consider this statement:
String s = new String("stringette"); // DON'T DO THIS!
The statement creates a new
String
instance each time it is executed, and none of those object creations is necessary. The argument to the String constructor ("stringette"
) is itself a String instance, functionally identical to all of the objects created by the constructor. If this usage occurs in a loop or in a frequently invoked method, millions of String instances can be created needlessly. The improved version is simply the following:String s = "stringette";
This version uses a single
String
instance, rather than creating a new one each time it is executed. Furthermore, it is guaranteed that the object will be reused by any other code running in the same virtual machine that happens to con- tain the same string literal [JLS, 3.10.5]
然而,有一种情况下你需要使用new String(String)
构造函数:当你想要强制将子字符串复制到一个新的底层字符数组中时,就像这样:
String tiny = new String(huge.substring(0, 10));
这将允许原始的huge
字符串中的大型底层char[]
被垃圾回收器回收利用。
tiny = new String(huge.substring(0, 10));
可以被垃圾回收吗?另一方面,为什么 tiny = huge.substring(0, 10);
不可以? - Sujeetiny = huge.substring(0, 10)
,tiny
将使用与 huge
相同的 char[]
。而使用 String tiny = new String(huge.substring(0, 10))
,tiny
将使用一个新的(较小的)char[]
,允许大的 char[]
被回收利用。有关详细信息,请查看源代码。 - Pascal Thiventnew String(String)
有一个微妙之处,请参见 https://dev59.com/4nRC5IYBdhLWcg3wKtv2#390854。 - Lawrence Dol如果你知道字符串是什么,就不要使用新的String
对象。例如:
String str = new String("foo"); // don't do this
因此,您正在创建一个不必要的对象 - 一旦您从字面上创建了一个String
对象,然后您创建另一个对象,以第一个对象作为构造函数参数。
String a = "ABC";
String b = new String("ABC");
String c = "ABC";
a == b // false
a == c // true
a.equals(b) // true
a.equals(c) // true
String.substring()
防止原始字符串被垃圾回收,所以当你写代码时可以节省内存。String s = new String(veryLongString.substring(1,3));
替代
String s = veryLongString.substring(1,3);
new String(String)
有一个微妙之处;请参见 https://dev59.com/4nRC5IYBdhLWcg3wKtv2#390854。 - Lawrence DolString s = "foo"
,编译器将检查堆上是否存在一个现有的“foo”对象,并将's'分配给已经存在的“foo”。String s = new String("foo")
,将在堆上创建一个全新的对象(即使已经存在“foo”)。由于字符串是不可变的,这是完全不必要的。字面字符串是在字符串池中创建的对象,如果它们具有相同的值,则引用同一个对象。
System.out.println("abc"=="abc"); // the output is true
与此同时,字符串对象是内存中的真实对象,如果它们具有相同的值,则不能保证它们引用同一个对象。
String a = new String("abc");
String b = new String("abc");
System.out.println(a==b); // the output is false
int
vs. 常量)。会导致魔法数字 vs. “不是全局参数,只需要用一次…” 等等。 - Konrad Garusconst int a = 1; *(int*)&a = 2;
这样的代码之后,1 就会全局地变成 2... - pascalString s = new String("xx")
上。这就是你所说的吗? - pascal