Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何认为这是不可变的?_Java - Fatal编程技术网

Java 如何认为这是不可变的?

Java 如何认为这是不可变的?,java,Java,根据我对Java的理解,字符串是不可变的。因此,下面的内容不会连接,只会给我输出app,证明它是不可变的。我明白了 String apple = new String("app"); apple.concat("le"); System.out.println(apple); 但是我可以在用一些值初始化字符串后更改它的值。这不是被认为是不变的吗 String orange = "ora"; orange = "orange"; System.out.println(orange); 根据维基

根据我对Java的理解,字符串是不可变的。因此,下面的内容不会连接,只会给我输出app,证明它是不可变的。我明白了

String apple = new String("app");
apple.concat("le");
System.out.println(apple);
但是我可以在用一些值初始化字符串后更改它的值。这不是被认为是不变的吗

String orange = "ora";
orange = "orange";
System.out.println(orange);

根据维基百科,不可变对象是:

创建后无法修改其状态的对象

但是,您没有修改原始的橙色
字符串对象
“ora”
):您正在创建一个新的
字符串对象
“orange”
),并且该新对象被分配给一个变量


轻而易举 如果这不合理,就这样想吧。假设某个
对象
是一块巧克力蛋糕,您可以在不改变蛋糕特性的情况下添加糖衣或切下部分蛋糕。但是,如果您想将其更改为红色天鹅绒蛋糕,则必须制作一个新的蛋糕,因为您无法修改巧克力蛋糕使其成为原始的红色天鹅绒蛋糕(出于实际目的)。一个不可变的对象意味着你不能切割,或者冰。。。这个“蛋糕”,但是你可以用一个新的蛋糕来代替它。

orange=“orange”
只意味着
orange
指向一个新的
String
实例,而不是旧的(
“ora”

不变性意味着您无法在对象创建后更改其状态。您尚未更改
orange
所引用的字符串实例的状态;您刚刚使它引用了一个新实例。更改对象的状态需要调用该对象上更改其状态的方法,或者修改其可公开访问的属性之一

您还混淆了对象的不变性和引用的不变性。要使引用不可变(即,确保初始化后无法使其指向其他对象),请使用
final
关键字

如果你有:

final String orange = "ora";
orange = "orange";

您现在会收到一个错误,因为引用是不可变的,无法重新分配。

对象是不可变的,引用是不可变的。您可以使用orange=“orange”随时更改引用,但您不会更改对象。您只是在放弃旧的引用并将引用附加到新的引用。

当您这样做时:

orange = "orange";
幕后发生的是:

orange = new String("orange");
也就是说,
orange
,作为对
字符串的引用,被修改。它只是指向一个不同的
字符串
实例

在本声明中:

apple.concat("le");
所发生的情况是,您创建了一个新的
字符串
对象,它是
apple.concat(新字符串(“le”)
的结果,但您没有分配它

但是,你在这里再次处理字符串;字符串是Java中少数几个具有内置行为的类之一,例如:

final String x = "a" + "b";
这实际上意味着:

final String x = new StringBuilder("a").append("b").toString();

你已经踏入了黄蜂窝。

String
类的实例是不可变的。
apple
变量不是不可变的,但如果您将其声明为
final
,它将是不可变的

例如,以下代码正在修改对象:

Person p = new Person("John");
p.setName("Jenny"); // <-- mutating
p
只需更新以引用不同的
Person
对象。原始的“John”对象仍然存在(直到垃圾被回收)

现在,如果
p
被定义为
final
,那么它(变量)也是不可变的:

final Person p = new Person("John");
// Cannot: p = new Person("Jenny");
在您的特定情况下,
concat
不会改变
字符串
,它会创建一个新字符串并返回它,因此您需要:

String apple = new String("app");
apple = apple.concat("le");
System.out.println(apple); // prints "apple"

此处更新变量,但不更新
字符串
对象。

对象
不可变,而引用不可变。可以更改引用,但不能更改对象

添加一个示例使我们更清楚
您应该阅读任何优秀的java初学者书籍
orange=“orange”
orange=新字符串(“orange”)相同(为了参数)(是的,存在一些内部/技术上的差异,但为了论证)“证明它是不可变的”-否。它证明它可以返回一个新的(不可变的)字符串,该字符串是它(不可变的字符串)和另一个(不可变的)字符串的串联。执行此操作时,不可变的含义是
orange=“orange”上一个字符串对象“ora”仍然存在,并且没有发生变化。“orange”是一个新创建的字符串对象。我相信简单的答案是,当人们可以在不需要解释自己的情况下否决投票时,他们会很高兴。这是有道理的。感谢您的详细解释。“幕后发生的是:
orange=newstring(“orange”);
”我对此深表怀疑。“这实际上翻译成:
final String x=new StringBuilder(“a”).append(“b”).toString();
”这也不正确。不能使用StringBuilder连接文字。@Tom是的,它们是;检查JLSI猜测您是指在编译时对编译时常量表达式求值的部分?我不是应该检查这一点的人。看到不正确的部分“
final String x=“a”+“b”
实际上被翻译成:
final String x=new StringBuilder(“a”).append(“b”).toString();
”仍然在回答中,这很令人难过:(。虽然这是真的,但问题的程度决定了要给出一个例子(这里无意冒犯OP)……特别是因为我们这里处理的字符串常量经过编译器的特殊处理。@fge实际上,您的答案是错误的,因为
orange=“orange”
并不意味着
orange=new string(“orange”)
。如果是,那么
a=“X”;b=“X”
会将两个不同的对象分配给
a
b
,但事实并非如此。它们都获得相同的对象引用。t
String apple = new String("app");
apple = apple.concat("le");
System.out.println(apple); // prints "apple"
String orange1 = "ora";
String orange2 = orange1;
System.out.println("orange1: " + orange1 +  " , orange2: " + orange2);
System.out.println("----------------------");
orange2 = "orange";
System.out.println("orange1: " + orange1 +  " , orange2: " + orange2);