在Java中,“new String(“xyz”)”和““xyz””之间的区别是什么?

3

可能是重复内容:
字符串对象和字符串字面量的区别

你好,

首先,让我们来谈谈Java中的String。

字符串是不可变的 我的问题是:如果字符串是不可变的,那么下面的语句应该会编译错误!

             String str = "xyz";
                     or
             String str = new String("xyz");

             str = "abc";        //COMPILATION ERROR
                 or
             str = new String("abc");  //COMPILATION ERROR

下面两种实例化方式有什么区别?
 String str = "xyz";
      and
 String str = new String("xyz");

Amit. (阿米特)

1
只是一个提示:字符串值是不可变的,而不是包含它们的变量。 - Farshid Zaker
5个回答

5

字符串是不可变的,这意味着您不能执行像 str[1] = 'x' 这样的操作,即您无法更改字符串的内容。

这里将回答您的第二个问题。


str[1]是字符串数组。如果我只声明了String str = "xyz",我该如何编写上述语句? - Amit Yadav
@Amit:String 就是一个字符数组。因此,你不能替换 String 的内部内容,因为 String 是不可变的。 - Saurabh Gokhale

3

字符串是不可变的,因此您无法更改字符串的内容。

在下面的代码中:

String str = "xyz";
str = "abc";

您并没有改变字符串实例的内容,而是将一个新的字符串实例赋值给变量str。也就是说,如果您执行以下操作:

String str = "xyz";
String otherStr = str;
String str = "abc";

此时otherStr保持不变。所以你实际上没有改变str指向的对象。

至于你的第二个问题

String str = "xyz";

从字符串池中获取值为"xyz"的String对象。
String str = new String("xyz");

实例化一个新对象。

也就是说,如果您执行

String a = "xyz", b = "xyz";

如果你执行a == b,则会得到相等的结果。

String a = new String("xyz"), b = new String("xyz");

这不会是问题。示例

更多信息,请参见:


2

字符串是不可变的。但是字符串的引用是可变的。这就是它们之间的区别。

因此:

String str = "abc";

str是一个变量,指的是一个不可变的字符串"abc"。如果我执行以下操作:

str = "def";

str仍然是一个变量,指向另一个不可变的字符串("def")。无论我如何改变str所指向的位置,str都是一个变量。 我不能更改任何字符串的实际内容(因为Java的字符串是设计为不可变的)。每当您执行似乎修改字符串的操作(比如 toUpperCase),实际上是创建一个包含旧字符串内容副本、按照描述方式修改后的字符串。

将字符串设置为不可变的目的在于,如果我有一个对字符串的引用,那么这个字符串永远不会发生更改。当传递字符串时,这是一种非常有用的保证。如果我们没有这个保证,我们就必须一直复制字符串,以保护自己免受他人修改。例如,考虑一个name属性的标准设置函数:

void setName(String n) {
    this.name = n;
}

如果字符串不是不可变的,我们就必须这样做:
void setName(String n) {
    this.name = new String(n); // Blech, duplication
}

关于字符串的不可变性,Java的设计者非常聪明地决定让字符串成为不可变对象,以确保我们的字符串副本不会以我们意想不到的方式发生更改。这将导致大量的字符串数据在内存中重复,其中大部分都是不必要的。因此,如果您需要进行任何更改,则会创建一个新字符串而不是就地修改旧字符串。(对于那些确实需要的情况,您可以使用char[]来获得就地修改行为。)


关于您提出的关于str = "abc";str = new String("abc")之间差异的问题,其区别是后者(使用构造函数)保证返回一个新的引用,而前者则没有。例如:

String a = "abc";
String b = "abc";
String c = new String("abc");

a == b(检查引用是否匹配,而不是字符串)将返回true,因为字面字符串已被内部化。保证a == c为false,因为我们使用了c的构造函数。a.equals(b)a.equals(c)都将返回true,因为abc都引用到相等的字符串。


@Crowder;这是关于“Blech,重复”的问题。假设我有两个类A和B,在B的构造函数中,我传递了A的引用。通常我们会写一个代码A a; //声明一个全局变量,并在构造函数中简单地写入this.a=${passed reference},我的意思是说我们不使用new运算符来实现...你能详细解释一下吗?(2)如何使我的自定义类成为不可变类? - Amit Yadav
@Amit:这听起来像是个笑话,但并不是:要使自己的类成为不可变类,不要提供任何改变器函数。例如,如果 A 接受 foobar 作为构造函数参数,并通过 getFoogetBar 方法使它们可用,不要提供 setFoosetBar 改变器方法。然后确保以下两点之一:1)在构造函数中接受的事物是不可变的(在这种情况下,您可以像现在一样使用给定的引用),或者 2)如果您接受的是任何可变的东西,请为自己使用制作一个副本,以便没有东西能够更改您的副本。 - T.J. Crowder

1
如果字符串是不可变的,那么下面的语句应该会编译错误!
你误解了不可变性的概念。看看Prasoon的回答。
字符串的不可变性意味着你不能更改字符串内部的内容。
String a = "hello";
String b = "hello";    
System.out.println(a==b);   // returns true.

这里的ab都是字符串字面量,它们指向同一个对象。


两个实例之间的区别是什么?
String a = "hello";
String b = "hello";   
System.out.println(a==b); // returns true.

两者都指向相同的字符串字面量。

String a = new String("hello");
String b = new String("hello"); 
System.out.println(a==b);  // returns false.

创建了两个不同的字符串对象。


0
 String str = "xyz"; 

是一个内部缓存的字符串实例。

 String str = new String("xyz");

是一个新的对象,没有从缓存中实例化

顺带一提,以下是它的行为...

"xyz" == "xyz" evals true

new String("xyz") == new String("xyz") evals false

new String("xyz").equals(new String("xyz")) evals true

请注意,在Java中==会比较对象的引用。

你能否解释一下为什么使用equals()返回true? - Amit Yadav
equals 实现字符串内容比较,如果相等则返回 true。 == 用于测试对象在内存中的引用是否相等,当重复使用缓存中的实例时将返回 true。 - Manuel Salvadores

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接