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)如果您接受任何可变的内容,请制作一个副本供您自己使用,这样就不会更改您的副本。