[英]java immutable object question
String abc[]={"abc"};
String def[]={};
def=abc;
def[0]=def[0]+"changed";
System.out.println(abc[0]);
by changing "def" object, my abc object is changed as well. 通过更改“def”对象,我的abc对象也会被更改。 Beside String[] array has this characteristic what other java object has similar characteristic?
String []数组旁边有哪些其他java对象具有相似特性的特性? can explain more?
可以解释一下吗? in order to prevent abc from changed when i changed def, i will have to do def = abc.clone();
为了防止在我改变def时改变abc,我将不得不做def = abc.clone();
You are confusing object mutability/immutability with copying of reference values. 您将对象可变性/不可变性与复制参考值混淆。
In these diagrams, [var/index]
is a reference variable, and {{an Object}}
is an object. 在这些图中,
[var/index]
是一个引用变量, {{an Object}}
是一个对象。
String abc[]={"abc"};
String def[]={};
[abc] ------> {{a String[1]}}
[0] --------------> {{a String "abc"}}
[def] ------> {{a String[0]}}
Now you make def
reference variable points to the same object as abc
reference variable: 现在,您将
def
引用变量指向与abc
引用变量相同的对象:
def=abc;
[abc] ------> {{a String[1]}}
/ [0] --------------> {{a String "abc"}}
/
[def] ---/ {{a String[0]}}
At this point, the array of length zero is unreferenced, and should be garbage-collectable. 此时,长度为零的数组未被引用,并且应该是可垃圾收集的。 We can narrow our discussion to the array of length one.
我们可以将讨论范围缩小到长度为一的数组。 Note that a
String[]
is an array of references. 请注意,
String[]
是一个引用数组。 With this next line, you changed what the only element in the length one array points to. 在下一行中,您更改了一个数组指向的长度中唯一的元素。
def[0]=def[0]+"changed";
[abc] ------> {{a String[1]}}
/ [0] ---------\ {{a String "abc"}}
/ \
[def] ---/ \--> {{a String "abcchanged"}}
Note that {{a String "abc"}}
itself was not mutated. 请注意
{{a String "abc"}}
本身未发生变异。 [abc]
and [def]
now points to the same {{a String[1]}}
, which is mutable (ie you can make the elements of the array, which are references to String
objects, to point to anything). [abc]
和[def]
现在指向相同的{{a String[1]}}
,这是可变的(即你可以使数组的元素,即String
对象的引用,指向任何东西)。
in order to prevent
abc
from changed when i changeddef
, i will have to dodef = abc.clone()
;为了防止在我改变
def
时改变abc
,我将不得不做def = abc.clone()
;
Actually, that's not quite accurate. 实际上,这不太准确。 Let's see what happens if you
clone()
an array of references to a mutable type StringBuilder
. 让我们看看如果
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!"
I won't make the diagrams for you this time, but you can easily draw it out on paper. 这次我不会为你制作图表,但你可以很容易地在纸上画出来。 What's happening here is that even though
clone()
makes a second {{a StringBuilder[1]}}
object with its own element (ie def != abc
), that element is pointing to the same {{a StringBuilder}}
object (ie def[0] == abc[0]
). 这里发生的事情是,即使
clone()
使用自己的元素(即def != abc
)生成第二个{{a StringBuilder[1]}}
对象,该元素也指向同一个{{a StringBuilder}}
对象(即def[0] == abc[0]
)。
In short: 简而言之:
Integer
, String
, etc are immutable Integer
, String
等是不可变的 If you want more in-depth understanding of the issues, I recommend the following: 如果您想更深入地了解这些问题,我建议如下:
Immutable objects are objects that cannot be changed once created. 不可变对象是一旦创建就无法更改的对象。
String
is an obvious example. String
是一个明显的例子。 Arrays are mutable. 数组是可变的。 If you want an immutable collection, use a
List
instead: 如果您想要一个不可变的集合,请改用
List
:
List<String> abc = Collections.unmodifiableList(
Arrays.asList("abc")
);
Mutable objects have mutators . 可变对象有变异器 。 A mutator is any method that modifies the state of the object.
mutator是修改对象状态的任何方法。 Setters are an obvious example.
塞特斯是一个明显的例子。 A typical immutable object will look like this:
典型的不可变对象将如下所示:
public class Person {
private final String firstName;
private final String lastName;
private final Date dateOfBirth;
public Person(String firstName, String lastName, Date dateOfBirth) {
this.firstName = firstName;
this.lastName = lastName;
this.dateOfBirth = new Date(dateOfBirth.getTime());
}
public String getFirstName() { return firstName; }
public String getLastname() { return lastName; }
public Date getDateOfBirth() { return new Date(dateOfBirth.getTime()); }
}
Generally speaking, for immutable objects, all members are final
and immutable. 一般来说,对于不可变对象,所有成员都是
final
和immutable。 Date
is a good example of the issue above. Date
是上述问题的一个很好的例子。 Date
is not immutable, which many (myself included) consider a design mistake. Date
不是一成不变的,许多人(包括我自己)认为这是设计错误。 As a result of it being mutable you have to do lots of defensive copying. 由于它是可变的,你必须进行大量的防御性复制。
just to be pedantic, there's no "abc" object or "def" object. 只是为了迂腐,没有“abc”对象或“def”对象。 There's the single String[] that abc, and then def happen to refer to.
有单个String [] abc,然后def碰巧引用。 That's why "both objects" changed.
这就是为什么“两个对象”都改变了。 They were, in fact, referring to the same object.
事实上,他们指的是同一个对象。
In simple terms it is like this :- Lets assume Sample to be a class then, 简单来说就是这样: - 假设Sample是一个类,那么,
Sample sam1 = new Sample();
will clearly be explained as sam1 being the reference to the object created. 将清楚地解释为sam1是对创建的对象的引用。 but
但
Sample sam2;
just declares sam2 to be a reference variable of Sample type and has no object of Sample class being pointed by it. 只是声明sam2是Sample类型的引用变量,并且它没有指向Sample类的对象。 now if we do this operation
现在如果我们做这个操作
sam2 = sam1;
then it means both the reference variables point to the same object and now one can refer to that object using any one of the two references. 那么这意味着两个引用变量都指向同一个对象,现在可以使用两个引用中的任何一个来引用该对象。 Obviously one can manipulate the fields employing the valid methods using either of the references.
显然,可以使用任一参考文献来使用有效方法来操纵字段。 And this is what has been done here too.
这也是这里所做的。
String abc[]={"abc"};
String def[]={};
def=abc;
def[0]=def[0]+"changed";
and so changing def[0] changes abc[0] too. 所以改变def [0]也会改变abc [0]。
Now when you clone you are creating a clone of the existent object.
The clone and the cloned objects independently exist
as 2 different objects and so the result of manipulations on one
is not reflected as you stated.
In java, you can always change the elements in an array, regardless of the type of the array. 在java中,无论数组的类型如何,您都可以随时更改数组中的元素。 Consider making a separate copy of the data in order to protect the initial value of abc if you would like to keep the data in an array structure:
如果要将数据保存在数组结构中,请考虑单独创建数据副本以保护abc的初始值:
String abc[]={"abc"};
String def[];
def = Arrays.copyOf(abc, abc.length);
Alternatively, use cletus solution: 或者,使用cletus解决方案:
List abc = Collections.unmodifiableList(
Arrays.asList("abc")
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.