java复制代码_Java编程实现对象克隆(复制)代码详解克隆,想必⼤家都有⽿闻,世界上第⼀只克隆⽺多莉就是利⽤细胞核移植技术将哺乳动物的成年体细胞培育出新个体,甚为神奇。其实在Java中也存在克隆的概念,即实现对象的复制。
本⽂将尝试介绍⼀些关于Java中的克隆和⼀些深⼊的问题,希望可以帮助⼤家更好地了解克隆。
假如说你想复制⼀个简单变量。很简单:
int apples = 5;
int pears = apples;
不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适⽤于该类情况。
但是如果你复制的是⼀个对象,情况就有些复杂了。
假设说我是⼀个beginner,我会这样写:
class Student {
private int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
public class Test {
public static void main(String args[]) {
Student stu1 = new Student();
stu1.setNumber(12345);
Student stu2 = stu1;
System.out.println("学⽣1:" + Number());
System.out.println("学⽣2:" + Number());
}
}
结果:
学⽣1:12345
学⽣2:12345
这⾥我们⾃定义了⼀个学⽣类,该类只有⼀个number字段。
我们新建了⼀个学⽣实例,然后将该值赋值给stu2实例。(Student stu2 = stu1;)
再看看打印结果,作为⼀个新⼿,拍了拍胸腹,对象复制不过如此,
难道真的是这样吗?
我们试着改变stu2实例的number字段,再打印结果看看:
stu2.setNumber(54321);
System.out.println("学⽣1:" + Number());
System.out.println("学⽣2:" + Number());
结果:
学⽣1:54321
学⽣2:54321
这就怪了,为什么改变学⽣2的学号,学⽣1的学号也发⽣了变化呢?
原因出在(stu2 = stu1) 这⼀句。该语句的作⽤是将stu1的引⽤赋值给stu2,
这样,stu1和stu2指向内存堆中同⼀个对象。如图:
那么,怎样才能达到复制⼀个对象呢?
是否记得万类之王Object。它有11个⽅法,有两个protected的⽅法,其中⼀个为clone⽅法。
在Java中所有的类都是缺省的继承⾃Java语⾔包中的Object类的,查看它的源码,你可以把你的JDK⽬录下的src.zip复制到其他地⽅然后解压,⾥⾯就是所有的源码。发现⾥⾯有⼀个访问限定符为protected的⽅法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 x, the expression:
1) x.clone() != x will be true
2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.
3) x.clone().equals(x) will be true, this is not an absolute requirement.
*/
protected native Object clone() throws CloneNotSupportedException;
仔细⼀看,它还是⼀个native⽅法,⼤家都知道native⽅法是⾮Java语⾔实现的代码,供Java程序调⽤的,因为Java程序是运⾏在JVM虚拟机上⾯的,要想访问到⽐较底层的与操作系统相关的就没办法了,只能由靠近操作系统的语⾔来实现。
第⼀次声明保证克隆对象将有单独的内存地址分配。
第⼆次声明表明,原始和克隆的对象应该具有相同的类类型,但它不是强制性的。
第三声明表明,原始和克隆的对象应该是平等的equals()⽅法使⽤,但它不是强制性的。
因为每个类直接或间接的⽗类都是Object,因此它们都含有clone()⽅法,但是因为该⽅法是protected,所以都不能在类外进⾏访问。
要想对⼀个对象进⾏复制,就需要对clone⽅法覆盖。
为什么要克隆?
⼤家先思考⼀个问题,为什么需要克隆对象?直接new⼀个对象不⾏吗?
答案是:克隆的对象可能包含⼀些已经修改过的属性,⽽new出来的对象的属性都还是初始化时候的值,所以当需要⼀个新的对象来保存当前对象的“状态”就靠clone⽅法了。那么我把这个对象的临时属性⼀个⼀个的赋值给我新new的对象不也⾏嘛?可以是可以,但是⼀来⿇烦不说,⼆来,⼤家通过上⾯的源码都发现了clone是⼀个native⽅法,就是快啊,在底层实现的。
提个醒,我们常见的Object a=new Object();Object b;b=a;这种形式的代码复制的是引⽤,即对象在内存中的地址,a和b对象仍然指向了同⼀个对象。
⽽通过clone⽅法赋值的对象跟原来的对象时同时独⽴存在的。
如何实现克隆
先介绍⼀下两种不同的克隆⽅法,浅克隆(ShallowClone)和深克隆(DeepClone)。
在Java语⾔中,数据类型分为值类型(基本数据类型)和引⽤类型,值类型包括int、double、byte、boolean、char等简单数据类型,引⽤类型包括类、接⼝、数组等复杂类型。浅克隆和深克隆的主要区别在于是否⽀持引⽤类型的成员变量的复制,下⾯将对两者进⾏详细介绍。
⼀般步骤是(浅克隆):
1. 被复制的类需要实现Clonenable接⼝(不实现的话在调⽤clone⽅法会抛出CloneNotSupportedException异常), 该接⼝为标记接⼝(不含任何⽅法)
2. 覆盖clone()⽅法,访问修饰符设为public。⽅法中调⽤super.clone()⽅法得到需要的复制对象。(native为本地⽅法)
下⾯对上⾯那个⽅法进⾏改造:
class Student implements Cloneable{
private int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public Object clone() {
Student stu = null;
try{
stu = (Student)super.clone();
}
catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return stu;
}
}
public class Test {
public static void main(String args[]) {
Student stu1 = new Student();
java爱心代码编程简单stu1.setNumber(12345);
Student stu2 = (Student)stu1.clone();
System.out.println("学⽣1:" + Number());
System.out.println("学⽣2:" + Number());
stu2.setNumber(54321);
System.out.println("学⽣1:" + Number());
System.out.println("学⽣2:" + Number());
}
}
结果:
学⽣1:12345
学⽣2:12345
学⽣1:12345
学⽣2:54321
如果你还不相信这两个对象不是同⼀个对象,那么你可以看看这⼀句:System.out.println(stu1 == stu2); // false
上⾯的复制被称为浅克隆。
还有⼀种稍微复杂的深度复制:
我们在学⽣类⾥再加⼀个Address类。
class Address {
private String add;
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
}
class Student implements Cloneable{ private int number;
private Address addr;
public Address getAddr() {
return addr;
}
public void setAddr(Address addr) { this.addr = addr;
}
public int getNumber() {
return number;
}
public void setNumber(int number) { this.number = number;
}
@Override
public Object clone() {
Student stu = null;
try{
stu = (Student)super.clone();
}
catch(CloneNotSupportedException e) { e.printStackTrace();
}
return stu;
}
}
public class Test {
public static void main(String args[]) { Address addr = new Address();
addr.setAdd("杭州市");
Student stu1 = new Student();
stu1.setNumber(123);
stu1.setAddr(addr);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论