我有一个班级,
class MyClass {
private int val;
public static final MyClass myObject = new MyClass(1);
MyClass(int a){
val = a;
}
public int getVal(){
return val;
}
public MyClass func1(){
MyClass temp = myObject;
temp.val = 2;
return temp;
}
public static void main(String [] args){
MyClass x = new MyClass(4);
System.out.println(myObject.getVal());
x.func1();
System.out.println(myObject.getVal());
}
}
打印:
1
2
我期待它打印出来:
1
1
我似乎存在一个根本性的误解。我希望无法更改myObject
为final static
的值,当我执行MyClass temp = myObject
时,我会创建一个名为temp
的{{1}}类型的新对象,将MyClass
的值分配给此新创建的对象。如果我错了,请纠正我。似乎没有创建新对象,myObject
只是指向原始temp
myObject
运算符永远不会复制对象,它只是复制引用。我需要的是复制=
并将其存储在myObject
中。实现这一目标的最佳方法是什么?
EDIT2:Java的另一个奇怪的行为或特征?
我稍微修改了代码
temp
输出
class MyClass {
private Integer val;
public static final MyClass myObject = new MyClass(1);
MyClass(int a){
val = a;
}
public int getVal(){
return val;
}
public MyClass func1(){
MyClass temp = new MyClass(33);
temp.val = myObject.val;
temp.val = 2;
return temp;
}
public static void main(String [] args){
MyClass x = new MyClass(4);
System.out.println(myObject.getVal());
MyClass y = x.func1();
System.out.println(x.getVal());
System.out.println(y.getVal());
System.out.println(myObject.getVal());
}
}
因此,当我使用 1
4
2
1
创建temp
然后设置new MyClass(33)
时,它实际上会复制val。换句话说,temp.val = 2
并未指向temp.val
。为什么会这样?
答案 0 :(得分:7)
MyClass temp = myObject;
那不是创建一个新实例,它只是分配引用,以便temp指向与myObject相同的实例。
所以你的陈述:
我创建了一个名为temp of的新对象 输入MyClass
不正确,因为您没有在此处创建新对象,只需指定对象引用。
修改强>
如果您的目标是制作myObject的副本并从func1()
返回,那么您可以这样做(通过复制我假设您的意思是复制val
值,如果您想使用不同的val
的值,然后您可以相应地调整此代码):
public MyClass func1(){
MyClass temp = new MyClass(myObject.getVal());
return temp;
}
答案 1 :(得分:5)
该字段为final
,表示您无法重新分配该字段。但是,myObject
var不是不可变的。当您在func1()
上致电myObject
时,您正在将myObject.val
更改为2.
答案 2 :(得分:2)
您正在获取对MyClass对象的实例的引用并修改其中一个成员。该引用不是一成不变的;只有名为myObj的字段是不可变的。
答案 3 :(得分:1)
我认为你有点回答了你自己的问题。你说的是没有真正由行MyClass temp = myObject;
创建的新对象temp是正确的,temp只是对myClass的静态实例的对象引用。
您可以通过修改代码来检查这一点。
public MyClass func1(){
MyClass temp = myObject;
System.out.println(myObject == temp);//print true
temp.val = 2;
return temp;
}
答案 4 :(得分:1)
在Java中,=
运算符分配引用,而不是C ++中的对象。
最后一个字段只能分配一次。这并不意味着无法修改通过最终字段可到达的对象。
换句话说:与C ++的const
不同,final
只保护引用,而不是对象。
答案 5 :(得分:1)
阅读发布的答案后:
如果您希望临时引用变量保存引用。对于一个不可变对象,你可以使你的类不可变。
您可以在此处找到有关如何执行此操作的更多信息:
http://www.javapractices.com/topic/TopicAction.do?Id=29
或
http://java.sun.com/docs/books/tutorial/essential/concurrency/imstrat.html
答案 6 :(得分:0)
修饰符final的定义表明无法更改对象引用。 在第一个代码段
中public static final MyClass myObject = new MyClass(1);
myObject是一个指向val = 1的对象的最终引用。 但是,这并不意味着不能更改对象的内容。 函数func1()获取值为1的对象的引用,并将其val更改为2。 因此它是完全合法的。
对于第二个片段
public MyClass func1(){
MyClass temp = new MyClass(33);
temp.val = myObject.val;
temp.val = 2;
return temp;
}
public static void main(String [] args){
MyClass x = new MyClass(4); //line A
System.out.println(myObject.getVal()); //returns 1
MyClass y = x.func1(); //line B
System.out.println(x.getVal()); //line C
System.out.println(y.getVal()); //line D
System.out.println(myObject.getVal());
}
在A行创建了一个带有val 4的obj
在第B行调用func1,总结创建一个val = 33的新对象,然后将其更改为val = 1然后val = 2。
在C行,我们从在A行创建的obj得到输出4
在D行,我们从使用B行的变化中得到输出2
在E行,我们从静态最终对象得到输出1,该对象没有改变。