Java的clone方法

Author Avatar
Serical 3月 21, 2017
  • 在其它设备中阅读本文章
package com;

import java.util.Arrays;

public class Test {

    class Person implements Cloneable {
        private int id;
        private String name;
        private int[] ints;

        public Person() {
        }

        public int[] getInts() {
            return ints;
        }

        public void setInts(int[] ints) {
            this.ints = ints;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }


        @Override
        public String toString() {
            return "Person [id=" + id + ", name=" + name + ", ints="
                    + Arrays.toString(ints) + "]";
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            // 浅复制直接返回super.close()
            return super.clone();
            /* Person p = (Person) super.clone();
            // 深度复制需要每个引用成员都要复制,这里string并没有实现Cloneable接口
            // 使用起来基本没影响,或者暂时还不知道,但需要注意,
            // 使用时可能是自定义bean,可以实现Cloneable接口
            p.name = (String) name.clone();
            return p;*/
        }

    }

    public static void main(String[] args) {
        Person p = new Test().new Person();
        String a = "name";
        int[] ints = new int[]{100};
        p.setId(1);
        p.setName(a);
        p.setInts(ints);
        System.out.println(p);
        // 修改值后p2会变
        p.setId(2);
        System.out.println(p);
        // 复制引用
        Person p2 = p;
        System.out.println(p2 == p);

        // 复制对象
        try {
            Person p3 = (Person) p.clone();
            System.out.println(p3 == p);
            // 浅复制,string类型的还是同一个
            System.out.println(p3.getName() == p.getName());
            System.out.println(p3.getName().hashCode() +"--"+p.getName().hashCode());
            System.out.println(p3.getName() +"--"+p.getName());
            // 修改p的非引用类型值,不会影响p3的值
            a = "name name";
            // 修改p的引用类型值,会影响p3的值
            ints[0] = 31;
            System.out.println(p);
            System.out.println(p3);
            System.out.println(p3.getName() == p.getName());
            System.out.println(p3.getName() == p.getName());
            System.out.println(p3.getName().hashCode() +"--"+p.getName().hashCode());
            System.out.println(p3.getName() +"--"+p.getName());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

浅复制console输出

Person [id=1, name=name, ints=[100]]
Person [id=2, name=name, ints=[100]]
true
false
true
3373707--3373707
name--name
Person [id=2, name=name, ints=[310]]
Person [id=2, name=name, ints=[310]]
true
true
3373707--3373707
name--name

详情见这里
http://www.2cto.com/kf/201401/273852.html

深度复制另一个解决办法

package com;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;

public class Test implements Serializable{

    class Person implements Serializable{
        private int age;
        private String name;
        private int[] ints;

        public Person() {
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int[] getInts() {
            return ints;
        }

        public void setInts(int[] ints) {
            this.ints = ints;
        }

        @Override
        public String toString() {
            return "Person [age=" + age + ", name=" + name + ", ints="
                    + Arrays.toString(ints) + "]";
        }

    }

    /**
     * 深度复制方法
     * @方法名:deepClone 
     * @参数 @param p
     * @参数 @return
     * @参数 @throws Exception  
     * @返回类型 Object
     */
    public static Object deepClone(Person p) throws Exception {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bout);
        out.writeObject(p);

        ByteArrayInputStream sin = new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream in = new ObjectInputStream(sin);
        return in.readObject();
    }

    public static void main(String[] args) throws Exception {
        Person p = new Test().new Person();
        p.setAge(30);
        p.setName("name");
        int[] ints = new int[]{100};
        p.setInts(ints);

        // 复制前
        System.out.println(p);

        // 复制后
        Person p1 = (Person) deepClone(p);
        System.out.println(p1);

        // 修改引用类型值
        ints[0] = 31;
        System.out.println(p);
        // 只有直接引用的p改变了,p1没有改变
        System.out.println(p1);
    }
}
console输出
Person [age=30, name=name, ints=[100]]
Person [age=30, name=name, ints=[100]]
Person [age=30, name=name, ints=[31]]
Person [age=30, name=name, ints=[100]]