对象被克隆,但静态引用仍然存在?
我正在学习对象深层克隆,我有一个带有getInstance方法的employee类,它返回一个单例,并且克隆返回的对象。下面是类和测试类。
public class Employee implements Serializable , Cloneable {
public static Employee employee;
private String name;
private int age;
private Employee(){
}
public Employee(String name, int age) {
super();
this.name = name;
this.age = age;
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public static Employee getInstance(){
if(employee == null ){
employee = new Employee();
return employee;
}
return employee;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
对象深度复制测试类
public class CopyTest {
/**
* @param args
*/
public static void main(String[] args) {
try {
Employee original = Employee.getInstance();
original.setName("John");
original.setAge(25);
Employee cloned = (Employee)copy(original);
System.out.println("Original -->"+Employee.getInstance().getName());
cloned.getInstance().setName("Mark");
System.out.println("Cloned -->"+cloned.getInstance().getName());
System.out.println("Original -->"+Employee.getInstance().getName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Object copy(Object orig) {
Object obj = null;
try {
// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(orig);
out.flush();
out.close();
// Make an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()));
obj = in.readObject();
}
catch(IOException e) {
e.printStackTrace();
}
catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
return obj;
}
}
产量
Original -->John
Cloned -->Mark
Original -->Mark
问题
尽管我克隆了原始对象以创建它的副本,
Employee cloned = (Employee)copy(original);
我通过调用来修改克隆对象的属性
cloned.getInstance().setName("Mark");
正如您从控制台输出中看到的那样,它反映了原始对象。 我认为这是因为静态调用? ,我如何克服这一点? 我是否违反了我通过getInstance方法需要对象的单个实例的原则,然后我决定稍后创建对象的副本。
这是什么JAVA文件教程页面说:
在其声明中具有静态修饰符的字段称为静态字段或类变量。 他们与班级相关,而不是与任何对象相关联。 该类的每个实例共享一个类变量,它位于内存中的一个固定位置。 任何对象都可以更改类变量的值,但也可以在不创建类的实例的情况下操作类变量。
克隆对象cloned
是类的只是另一个对象。 它不会改变它没有参考的另一个对象。 您的调用cloned.getInstance()
返回所有对象都可以访问的静态对象employee
,因为静态对象与Class
关联,而不是与任何特定对象关联。 所以你调用cloned.getInstance().setName("Mark");
就等于Employee.employee.setName("Mark");
您正在为static
字段employee
Employee
实例设置名称
cloned.getInstance().setName("Mark");
^ static method call that returns the employee reference
并打印它
System.out.println("Cloned -->"+cloned.getInstance().getName());
^ static method call
您可能想要实际更改cloned
实例
cloned.setName("Mark");
System.out.println("Cloned -->"+cloned.getName());
静态字段大致意味着它将被每个对象共享。 无论您创建/克隆了多少个对象,您的getInstance()调用将返回相同的Employee。
因此,只要您将其名称设为Mark,您将永远在控制台中获得Mark。
例如:
Employee me = new Employee();
Employee.getInstance().setName("Mark");
System.out.println("me employee name? " + me.getInstance().getName());
如果您在控制台中显示“Mark”,请不要惊讶;)
有关实例和类(使用static关键字)成员之间差异的更多详细信息,请参阅本教程部分
链接地址: http://www.djcxy.com/p/6971.html