对象被克隆,但静态引用仍然存在?

我正在学习对象深层克隆,我有一个带有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

上一篇: Object is cloned , but static references still exists?

下一篇: Clearing primary keys after deep cloning an object