java基础(4)-Object的clone

当需要复制某个对象,但修改得到对象的值又不影响原有的对象,此时就需要clone.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Person implements Cloneable, Serializable {

    private String name;

    private Integer ruleId;

    private Male male;

    // 省去getter、setter

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class Male implements Serializable {
    private int age;

    private String color;

    public Male(String color) {
        this.color = color;
    }

    // 省去getter、setter


}

不使用clone时的情况,用’=’进行赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class CloneDemo {
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.setName("ukyu");
        System.out.println("p1 :" + p1);
        Person p2 = p1;
        p2.setName("hello world!");
        System.out.println("p1 :" + p1);
        System.out.println("p2 :" + p2);
        
    }
}
// output :
// p1 :Person{name='ukyu', ruleId=null, male=null}
// p1 :Person{name='hello world!', ruleId=null, male=null}
// p2 :Person{name='hello world!', ruleId=null, male=null}

使用’=’, 让两个引用指向了同一个内存区域,p2修改了name,p1也会变.

就相当于, 不使用clone时

1
2
3
4
5
6
7
8
9
10
// 使用clone,复制对象
// 只需要修改一行,还要抛出CloneNotSupportedException
// 要使用clone,必须实现Cloneable接口,不是就会抛出上面的错
Person p2 = (Person) p1.clone();

// output:
// p1 :Person{name='ukyu', ruleId=null, male=null}
// p1 :Person{name='ukyu', ruleId=null, male=null}
// p2 :Person{name='hello world!', ruleId=null, male=null}
// p1 与 p2的name互不影响

深拷贝与浅拷贝

浅拷贝: 对基本数据类型进行值传递,对引用数据类型进行引用传递

浅拷贝

深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容

深拷贝

clone是一种浅拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
// 对Male对象进行操作
        Person p1 = new Person();
        p1.setName("ukyu");
        p1.setMale(new Male("黄皮肤"));
        System.out.println("p1 :" + p1);
        Person p2 = (Person) p1.clone();
        p2.getMale().setColor("黑皮肤");
        System.out.println("p1 :" + p1);
        System.out.println("p2 :" + p2);
// output: 
// p1 :Person{name='ukyu', ruleId=null, male=Male{age=0, color='黄皮肤'}}
// p1 :Person{name='ukyu', ruleId=null, male=Male{age=0, color='黑皮肤'}}
// p2 :Person{name='ukyu', ruleId=null, male=Male{age=0, color='黑皮肤'}}

如果想对对象进行深拷贝,提供几个思路(在不引入其他jar包的情况下).

  • 将对象中引用的对象再次clone,即Male类也实现Cloneable,重写clone方法
  • 利用序列化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * @author ukyu
 * @date 2020/12/17
 **/

 // 利用序列化进行深拷贝
public class CloneUtils {

    @SuppressWarnings("unchecked")
    public static <T extends Serializable>T clone(T obj){
        T cloneObj = null;
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out =
                    new ObjectOutputStream(byteOut);
            out.writeObject(obj);
            out.close();

            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            cloneObj = (T)in.readObject();
            in.close();
            byteIn.close();
            byteOut.close();
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return cloneObj;
    }
}


对自己的现状不满意只有付出更多的努力去改变它

如果有不对的地方或建议,请指出,谢谢啦