假设我们创建String s
如下
String s = new String("Java");
因此,上面的声明将在遇到新运算符时创建一个新对象。
假设在同一个程序中,如果我们声明一个新的字符串 s1,如下所示:
String s1 = "Java";
这将创建一个新对象还是将它指向 Java 的旧对象,因为它已经使用上面的 new 运算符创建。
好吧,第二行不会创建新对象,因为您已经在第一行中使用了相同的字符串常量 - 但s1
仍然s
会引用不同的对象。
第二行不会创建新对象的原因是字符串常量被池化 - 如果您多次使用相同的字符串常量,它们都会被解析为相同的字符串。当然,在某个时候仍然必须String
分配一个对象——但所有用途都只有一个对象。例如,考虑以下代码:
int x = 0;
for (int i = 0; i < 1000000; i++) {
String text = "Foo";
x += text.length();
}
这不会创建一百万个字符串 - 的值text
在循环的每次迭代中都是相同的,每次都引用同一个对象。
但是如果你故意创建一个新 String
的,那肯定会创建一个新的对象——只是基于现有对象中的数据。例如:
String a = new String("test");
String b = new String("test");
String x = "test";
String y = "test";
// Deliberately using == rather than equals, to check reference equality
System.out.println(a == b); // false
System.out.println(a == x); // false
System.out.println(x == y); // true
或者换句话说,上面的前四行大致相当于:
String literal = "test";
String a = new String(literal);
String b = new String(literal);
String x = literal;
String y = literal;
String myString = new String("Java");
创建两个对象。
String myString = "Java";
创建一个对象。
字符串 s1="foo"; 文字将在 StringPool 中创建。
字符串 s2="foo"; 这次它将检查“foo”字面量是否已经在 StringPool 中可用,或者它现在是否存在,因此 s2 将引用与 s1 相同的字面量。
字符串 s3=new String("foo"); “foo”字面量将首先在 StringPool 中创建,然后通过字符串 arg 构造函数创建字符串对象,即由于通过 new 运算符创建对象而在堆中创建“foo”,然后 s3 将引用它。
为了创建一个新对象,我们使用new 关键字,Object
不使用 就无法创建new
。
根据第一个实例中的声明,Object
创建了一个新的,但在第二个实例中,您只声明了一个带有值的变量。
所以它不是一个Object
.
当您使用文字创建字符串时(例如 String str = "Hello";),对象不在堆中创建,它仅在 StringPool 中可用,但是当您使用“new”运算符创建字符串时(例如 String str = new String ("Hello")) 然后创建 StringPool 中的 Object 以及 Heap 中的另一个对象。所以我们不必要地创建了两个对象。因此,使用文字创建字符串是首选方式。