Java Diff bet新字符串(“xyz”)和;xyz";在爪哇

Java Diff bet新字符串(“xyz”)和;xyz";在爪哇,java,string,instantiation,Java,String,Instantiation,可能重复: 你好, 最重要的是,让我们用字符串来描述Java事实 字符串是不可变的 我的问题-如果字符串是不可变的,那么下面的语句应该有编译错误 String str = "xyz"; or String str = new String("xyz"); str = "abc"; //COMPILATION ERROR or

可能重复:

你好,

最重要的是,让我们用字符串来描述Java事实

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

             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.

字符串是不可变的,这意味着您不能执行类似于
str[1]=“x”
的操作,即您不能更改字符串的内容


将回答您的第二个问题。

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

在以下代码中:

String str = "xyz";
str = "abc";
您没有更改字符串实例的内容,而是将新的字符串实例分配给变量
str
。也就是说,如果您这样做:

String str = "xyz";
String otherStr = str;
String str = "abc";
然后,
otherStr
将保持不变。因此,实际上您并没有更改
str
指向的对象

至于你的第二个问题

String str = "xyz";
从字符串池中获取值为“xyz”的字符串对象,而

String str = new String("xyz");
实例化一个新对象

也就是说,如果你这样做了

String a = "xyz", b = "xyz";
String a = new String("xyz"), b = new String("xyz");
您将拥有
a==b
,而如果您拥有

String a = "xyz", b = "xyz";
String a = new String("xyz"), b = new String("xyz");
事实并非如此

有关详细信息,请参阅:

如果字符串是不可变的,那么下面 语句应该有编译 错误

你误解了不变性的概念。看看普拉松的答案。
字符串不变性意味着您不能更改字符串内的内容

String a = "hello";
String b = "hello";    
System.out.println(a==b);   // returns true.
这里
a
b
两个字符串文本都引用同一个对象


两者之间有什么区别 实例化

两者都引用相同的字符串文字

String a = new String("hello");
String b = new String("hello"); 
System.out.println(a==b);  // returns false.
将创建两个不同的字符串对象

 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中的
==
比较对象引用。

字符串是不可变的。字符串引用不可用。这就是区别

因此:

str
是一个变量,表示不可变字符串“abc”。现在如果我这样做:

str = "def";
str
仍然是一个变量,表示不同的不可变字符串(“def”)。我可以更改
str
指向我想要的所有内容,
str
是一个变量。我不能更改任何字符串的实际内容(因为Java的字符串在设计上是不可变的)。无论何时,只要您执行一些似乎要修改字符串的操作(例如,
toUpperCase
),它实际上是在创建一个新字符串,其中包含旧字符串内容的副本,并按照所述方式进行修改

让字符串不可变的意义在于,我知道如果我有一个对字符串的引用,该字符串永远不会改变。这是传递字符串时非常有用的保证。如果我们没有这个保证,我们会一直复制字符串,只是为了保护自己不被别人修改。例如,考虑一个用于<代码>名称>代码>属性的标准SETER函数:

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)
都是真的,因为
a
b
c
都是指字符串。

str[1]是字符串数组。如果我刚刚声明String str=“xyz”@Amit:String只是一个字符数组,我怎么能像上面的语句那样写呢。因此,您不能替换字符串的内部内容,因为字符串是不可变的。只是一个提示:字符串值是不可变的,而不是包含的变量。您能解释一下为什么它使用equals()返回true吗?
equals
实现字符串内容比较,在这种情况下为true<代码>=将测试对象内存引用的相等性,当从缓存中重用实例时,该相等性将为真。@Crowder;这是关于“Blech,replication”,假设我有两个类A和B,在B构造函数中,我传递A的引用;通常我们写的代码是//声明一个全局变量,然后在构造函数中简单地写下它。a=${passed reference}我的意思是我们不使用new操作符来实现这一点……请您详细说明一下,以及(2)如何使我自己的类不可变?@Amit:这听起来像是个笑话,但它不是:要使您自己的类不可变,请不要提供任何mutator函数。例如,如果
A
接受
foo
bar
作为构造函数参数,并通过
getFoo
getBar
方法使它们可用,则不要提供
setFoo
setBar
mutator方法。然后确保1)您在构造函数中接受的内容是不可变的(在这种情况下,您可以只使用给定的引用,就像您现在所做的那样),或者2)如果您接受任何可变的内容,请制作一个副本供您自己使用,这样就不会更改您的副本。