java不可变对象问题

String abc[]={“abc”};

String def[]={};

def=abc;

def[0]=def[0]+"changed";

System.out.println(abc[0]);

通过更改“ def”对象,我的abc对象也被更改。在String

[]数组旁边有这个特性还有什么其他的Java对象有类似的特性?能解释更多吗?为了防止在更改def时更改abc,我必须执行def =

abc.clone();。

回答:

您将对象的可变性/不可变性与引用值的复制混淆了。

在这些图中,[var/index]是参考变量,{{an Object}}是对象。

String abc[]={"abc"};

String def[]={};

[abc] ------> {{a String[1]}}

[0] --------------> {{a String "abc"}}

[def] ------> {{a String[0]}}

现在,您将def参考变量指向与参考变量相同的对象abc

def=abc;

[abc] ------> {{a String[1]}}

/ [0] --------------> {{a String "abc"}}

/

[def] ---/ {{a String[0]}}

在这一点上,长度为零的数组是未引用的,应该是垃圾回收的。我们可以将讨论范围缩小到长度为1的数组。请注意,a

String[]是引用数组。在下一行中,您更改了一个数组指向的长度中唯一的元素。

def[0]=def[0]+"changed";

[abc] ------> {{a String[1]}}

/ [0] ---------\ {{a String "abc"}}

/ \

[def] ---/ \--> {{a String "abcchanged"}}

请注意,{{a String "abc"}}它本身并未突变。[abc][def]现在指向相同的{{a

String[1]}},这是可变的(例如,你可以让数组的元素,这是引用String对象,以点到任何东西)。


为了防止abc改变我改变def,我必须做def = abc.clone();

实际上,这不是很准确。让我们看看如果您clone()对可变类型的引用的数组StringBuilder

    StringBuilder[] abc = new StringBuilder[] { new StringBuilder("Hello") };

StringBuilder[] def = abc.clone();

def[0].append(" world!");

System.out.println(abc[0]); // prints "Hello world!"

这次我不会为您绘制图表,但是您可以轻松地将其绘制在纸上。这里发生的是,即使使用它自己的元素(即)clone()创建了第二个{{a

StringBuilder[1]}}对象def != abc,该元素仍指向同一{{a StringBuilder}}对象(即def[0] ==

abc[0])。


简而言之:

  • 不变性意味着某种类型的对象不能以任何有意义的方式改变给外部观察者

    • IntegerString等是不可变的
    • 通常,所有值类型应为

  • 数组对象是可变的

    • 它可能是对不可变类型的引用的数组,但是数组本身是可变的
    • 意味着您可以将这些引用设置为所需的任何内容
    • 对于基本数组也是如此
    • 一成不变的数组将不切实际

  • 可以共享对对象的引用

    • 如果对象是可变的,则通过所有这些引用都可以看到突变

以上是 java不可变对象问题 的全部内容, 来源链接: utcz.com/qa/398006.html

回到顶部