clone方法的使用
什么是clone()
首先看一下jdk中对clone方法的解释:
/**
* Creates and returns a copy of this object. The precise meaning
* of "copy" may depend on the class of the object. The general
* intent is that, for any object {@code x}, the expression:
* <blockquote>
* <pre>
* x.clone() != x</pre></blockquote>
* will be true, and that the expression:
* <blockquote>
* <pre>
* x.clone().getClass() == x.getClass()</pre></blockquote>
* will be {@code true}, but these are not absolute requirements.
* While it is typically the case that:
* <blockquote>
* <pre>
* x.clone().equals(x)</pre></blockquote>
* will be {@code true}, this is not an absolute requirement.
* <p>
* By convention, the returned object should be obtained by calling
* {@code super.clone}. If a class and all of its superclasses (except
* {@code Object}) obey this convention, it will be the case that
* {@code x.clone().getClass() == x.getClass()}.
* <p>
* By convention, the object returned by this method should be independent
* of this object (which is being cloned). To achieve this independence,
* it may be necessary to modify one or more fields of the object returned
* by {@code super.clone} before returning it. Typically, this means
* copying any mutable objects that comprise the internal "deep structure"
* of the object being cloned and replacing the references to these
* objects with references to the copies. If a class contains only
* primitive fields or references to immutable objects, then it is usually
* the case that no fields in the object returned by {@code super.clone}
* need to be modified.
* <p>
* The method {@code clone} for class {@code Object} performs a
* specific cloning operation. First, if the class of this object does
* not implement the interface {@code Cloneable}, then a
* {@code CloneNotSupportedException} is thrown. Note that all arrays
* are considered to implement the interface {@code Cloneable} and that
* the return type of the {@code clone} method of an array type {@code T[]}
* is {@code T[]} where T is any reference or primitive type.
* Otherwise, this method creates a new instance of the class of this
* object and initializes all its fields with exactly the contents of
* the corresponding fields of this object, as if by assignment; the
* contents of the fields are not themselves cloned. Thus, this method
* performs a "shallow copy" of this object, not a "deep copy" operation.
* <p>
* The class {@code Object} does not itself implement the interface
* {@code Cloneable}, so calling the {@code clone} method on an object
* whose class is {@code Object} will result in throwing an
* exception at run time.
*
* @return a clone of this instance.
* @throws CloneNotSupportedException if the object's class does not
* support the {@code Cloneable} interface. Subclasses
* that override the {@code clone} method can also
* throw this exception to indicate that an instance cannot
* be cloned.
* @see java.lang.Cloneable
*/
看到这里大家可能会很懵逼, 其实clone方法简单来说就是将一个对象的属性和方法都复制一个给另外一个相同类型的对象.注意:复制之后这个对象的地址就和原本对象不同了.
clone的分类
clone 大致分两种,但它们都要实现Cloneable接口,重写clone方法
影子克隆
这个克隆只是简单的将这个对象进行克隆, 不管对象里面有不有引用类的属性, 也就是说,这种克隆 , 它里面的引用类型的成员变量地址还是一样的;
代码分析
public class Person implements Cloneable {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public boolean equals(Object obj) {
Person p = (Person) obj;
return this.name.equals(p.getName()) && (this.age == p.getAge());
}
@Override
protected Object clone() throws CloneNotSupportedException {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void main(String args) throws CloneNotSupportedException {
Person p1 = new Person("小宇", 22);
Person p2 = (Person)p1.clone();
System.out.println(p1 == p2);
System.out.println(p1);
System.out.println(p2);
}
}
运行结果:
可以发现clone的p2 和p1的内容是完全相同
深度克隆
代码分析
public class Person implements Cloneable {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public boolean equals(Object obj) {
Person p = (Person) obj;
return this.name.equals(p.getName()) && (this.age == p.getAge());
}
@Override
protected Object clone() throws CloneNotSupportedException {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
public class Group implements Cloneable {
private String groupName;
private int groupId;
private Person p;
public Group(String groupName, int groupId, Person p) {
super();
this.groupName = groupName;
this.groupId = groupId;
this.p = p;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public int getGroupId() {
return groupId;
}
public void setGroupId(int groupId) {
this.groupId = groupId;
}
public Person getP() {
return p;
}
public void setP(Person p) {
this.p = p;
}
@Override
public boolean equals(Object obj) {
Group g = (Group) obj;
return (this.groupId == g.groupId) && this.groupName.equals(g.getGroupName()) && this.p.equals(g.getP());
}
@Override
public String toString() {
return "Group [groupName=" + groupName + ", groupId=" + groupId + ", p=" + p + "]";
}
@Override
public Object clone() throws CloneNotSupportedException {
// 深度克隆
Group group = null;
try {
group = (Group) super.clone();
group.p = (Person) this.p.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return group;
}
public static void main(String[] args) throws CloneNotSupportedException {
Group g = new Group("英语学习小组", 1, new Person("小宇", 22));
Group gCopy = (Group)g.clone();
System.out.println(gCopy.equals(g));
System.out.println(g == gCopy);
System.out.println(g);
System.out.println(gCopy);
}
}
运行结果:
可以发现深度克隆不仅仅对Grop进行了克隆, 对立面的Person同样进行了克隆, 也就是说所有的引用类型的地址都发生了改变;
运用
在编程的过程中当我们遇到需要使用一个引用类型, 但又不想去改变里面的内容的时候我们就可以使用克隆.