在阿里的java开发手册里面,有这样的一条建议,慎重的使用Object的Clone方法,这个方法是native方法,底层的实现是浅拷贝,那是什么是浅拷贝呢,指的是,当你的要clone的类的里面有自定义的bean,使用clone方法拷贝,改变这个bean的里面的一些属性,也会影响到拷贝出来的对象。这个就是浅拷贝,如果想使用clone实现生拷贝,就要使用深度遍历是拷贝
浅拷贝
public class Title implements Serializable {
//省略getset 和tostring
private String title;
public Title(String title) {
this.title = title;
}
}
public class Book implements Cloneable {
private String name;
private int age;
private Title title;
//省略getset方法
public Book(String name, int age, Title title) {
this.name = name;
this.age = age;
this.title=title;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
Title title = new Title("test1");
Book book = new Book("hhhh", 12, title);
Book clone = (Book)book.clone();
System.out.println(book);
System.out.println(clone);
System.out.println(book.getTitle());
book.getTitle().setTitle("test2");
System.out.println(clone);
}
}
结果
Book{name='hhhh', age=12, title=Title{title='test1'}}
Book{name='hhhh', age=12, title=Title{title='test1'}}
Title{title='test1'}
Book{name='hhhh', age=12, title=Title{title='test2'}}
深拷贝
需要引用依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
作者:happyjava
链接:https://juejin.im/post/5d425230f265da039519d248
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
public class Title implements Cloneable{
private String title;
public Title(String title) {
this.title = title;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public Object clone() throws CloneNotSupportedException {
Book newBook = (Book) super.clone();
newBook.title = (Title) this.title.clone();
return newBook;
}
结果
Book{name='hhhh', age=12, title=Title{title='test1'}}
Book{name='hhhh', age=12, title=Title{title='test1'}}
Title{title='test1'}
Book{name='hhhh', age=12, title=Title{title='test1'}}
这里如果要类具有clone的能力还要实现Cloneable接口,这个接口和Serializable一样,没有抽象方法,是一个标志类。否则会报错java.lang.CloneNotSupportedException
Object里面的clone是proteceted修饰的,所以,我们在重写这个方法的时候,注意修饰符要是proteceted或者是public
使用序列化来实现clone
除了使用java提供的clone方法来实现clone,也是使用序列化来实现clone的。
public static void main(String[] args) throws CloneNotSupportedException {
Book book = new Book();
book.setName("hhhh");
book.setAge(100);
Title title = new Title("test");
book.setTitle(title);
System.out.println(book);
byte[] serialize = SerializationUtils.serialize(book);
Book deserialize = SerializationUtils.deserialize(serialize);
System.out.println(deserialize==book);
System.out.println(deserialize.getTitle()==book.getTitle());
}
打印结果
Book{name='hhhh', age=100, title=Title{title='test'}}
false
false
一般在面试当中,考java基础的时候,会考到clone的这个知识点,要抓住一下的几点
1,Object的clone是浅拷贝
2,什么是浅拷贝和深拷贝
3,java实现深拷贝的常用两种方法,一个是深度遍历测试,比较麻烦,另外一个是序列化实现。
网友评论