精华内容
下载资源
问答
  • Java对象克隆

    2021-03-08 03:24:41
    Java不提供克隆(复制)对象的自动机制。克隆对象意味着逐位复制对象的内容。要支持克隆操作,请在类中实现clone()方法。Object类中的clone()方法的声明如下:protected Object clone() throws ...

    Java不提供克隆(复制)对象的自动机制。克隆对象意味着逐位复制对象的内容。要支持克隆操作,请在类中实现clone()方法。Object类中的clone()方法的声明如下:

    protected Object clone() throws CloneNotSupportedException

    clone()方法声明为protected。 因此,不能从客户端代码调用它。以下代码无效:

    Object obj = new Object();

    Object clone = obj.clone(); // Error. Cannot access protected clone() method

    需要在类中声明clone()方法为public来克隆类的对象。

    它的返回类型是Object。 这意味着将需要使用clone()方法转换返回值。

    假设MyClass是可克隆的。 克隆代码将如下所示

    MyClass mc = new MyClass();

    MyClass clone = (MyClass)mc.clone(); // Need to use a cast

    Object类中的clone()方法会抛出CloneNotSupportedException。要调用clone()方法,需要将调用放在try-catch块中,或者重新抛出异常。

    示例

    以下代码显示了如何实现克隆方法。

    class MyClass implements Cloneable {

    private double value;

    public MyClass(double value) {

    this.value = value;

    }

    public void setValue(double value) {

    this.value = value;

    }

    public double getValue() {

    return this.value;

    }

    public Object clone() {

    MyClass copy = null;

    try {

    copy = (MyClass) super.clone();

    } catch (CloneNotSupportedException e) {

    e.printStackTrace();

    }

    return copy;

    }

    }

    public class Main {

    public static void main(String[] args) {

    MyClass dh = new MyClass(100.00);

    MyClass dhClone = (MyClass) dh.clone();

    System.out.println("Original:" + dh.getValue());

    System.out.println("Clone :" + dhClone.getValue());

    dh.setValue(100.00);

    dhClone.setValue(200.00);

    System.out.println("Original:" + dh.getValue());

    System.out.println("Clone :" + dhClone.getValue());

    }

    }

    上面的代码生成以下结果。

    Original:100.0

    Clone :100.0

    Original:100.0

    Clone :200.0

    实例-2

    以下代码不从clone()方法返回对象类型,该方法仅在Java5或更高版本中编译。

    class MyClass implements Cloneable {

    public MyClass clone() {

    Object copy = null;

    return (MyClass)copy;

    }

    }

    下面的代码展示了如何做浅克隆。

    class MyClass implements Cloneable {

    private double value;

    public MyClass(double value) {

    this.value = value;

    }

    public void setValue(double value) {

    this.value = value;

    }

    public double getValue() {

    return this.value;

    }

    public Object clone() {

    MyClass copy = null;

    try {

    copy = (MyClass) super.clone();

    } catch (CloneNotSupportedException e) {

    e.printStackTrace();

    }

    return copy;

    }

    }

    class ShallowClone implements Cloneable {

    private MyClass holder = new MyClass(0.0);

    public ShallowClone(double value) {

    this.holder.setValue(value);

    }

    public void setValue(double value) {

    this.holder.setValue(value);

    }

    public double getValue() {

    return this.holder.getValue();

    }

    public Object clone() {

    ShallowClone copy = null;

    try {

    copy = (ShallowClone) super.clone();

    } catch (CloneNotSupportedException e) {

    e.printStackTrace();

    }

    return copy;

    }

    }

    public class Main {

    public static void main(String[] args) {

    ShallowClone sc = new ShallowClone(100.00);

    ShallowClone scClone = (ShallowClone) sc.clone();

    System.out.println("Original:" + sc.getValue());

    System.out.println("Clone :" + scClone.getValue());

    sc.setValue(200.00);

    System.out.println("Original:" + sc.getValue());

    System.out.println("Clone :" + scClone.getValue());

    }

    }

    上面的代码生成以下结果。

    Original:100.0

    Clone :100.0

    Original:200.0

    Clone :200.0

    实例-3

    ShallowClone类的clone()方法中的代码与MyClass类的clone()方法相同。当ShallowClone类使用super.clone()调用Object类的clone()方法时,它会接收自身的浅拷贝。也就是说,它与其克隆共享其实例变量中使用的DoubleHolder对象。

    在深克隆中,需要克隆对象的所有引用实例变量。

    class MyClass implements Cloneable {

    private double value;

    public MyClass(double value) {

    this.value = value;

    }

    public void setValue(double value) {

    this.value = value;

    }

    public double getValue() {

    return this.value;

    }

    public Object clone() {

    MyClass copy = null;

    try {

    copy = (MyClass) super.clone();

    } catch (CloneNotSupportedException e) {

    e.printStackTrace();

    }

    return copy;

    }

    }

    class DeepClone implements Cloneable {

    private MyClass holder = new MyClass(0.0);

    public DeepClone(double value) {

    this.holder.setValue(value);

    }

    public void setValue(double value) {

    this.holder.setValue(value);

    }

    public double getValue() {

    return this.holder.getValue();

    }

    public Object clone() {

    DeepClone copy = null;

    try {

    copy = (DeepClone) super.clone();

    copy.holder = (MyClass) this.holder.clone();

    } catch (CloneNotSupportedException e) {

    e.printStackTrace();

    }

    return copy;

    }

    }

    public class Main {

    public static void main(String[] args) {

    DeepClone sc = new DeepClone(100.00);

    DeepClone scClone = (DeepClone) sc.clone();

    System.out.println("Original:" + sc.getValue());

    System.out.println("Clone :" + scClone.getValue());

    sc.setValue(200.00);

    System.out.println("Original:" + sc.getValue());

    System.out.println("Clone :" + scClone.getValue());

    }

    }

    执行上面的代码,将生成以下结果 -

    Original:100.0

    Clone :100.0

    Original:200.0

    Clone :100.0

    ¥ 我要打赏

    纠错/补充

    收藏

    加QQ群啦,易百教程官方技术学习群

    注意:建议每个人选自己的技术方向加群,同一个QQ最多限加 3 个群。

    展开全文
  • 正文JAVA实现克隆有两种形式浅克隆克隆克隆与深克隆的区别JAVA将数据类型分为基本数据类型以及引用数据类型,我认为浅克隆与深克隆的区别主要在于对引用类型的成员属性的操作。深度克隆应该递归克隆引用类型的...

    前言

    这也是昨天的面试题。

    当时只说了深拷贝以及浅拷贝,面试官问了两遍还有吗,我很肯定的说就这两种了,面试结束之后查了一下,啪啪打脸。

    正文

    JAVA实现克隆有两种形式

    浅克隆

    深克隆

    浅克隆与深克隆的区别

    JAVA将数据类型分为基本数据类型以及引用数据类型,我认为浅克隆与深克隆的区别主要在于对引用类型的成员属性的操作。深度克隆应该递归克隆引用类型的成员属性。

    浅克隆实现

    实现Cloneable接口

    重写clone方法,调用父类的clone方法

    代码

    public class Text implements Cloneable{

    private int age;

    private Name name;

    public int getAge() {

    return age;

    }

    public void setAge(int age) {

    this.age = age;

    }

    public Name getName() {

    return name;

    }

    public void setName(Name name) {

    this.name = name;

    }

    @Override

    protected Object clone(){

    try {

    return super.clone();

    } catch (CloneNotSupportedException e) {

    e.printStackTrace();

    }

    return null;

    }

    }

    class Name{

    private String name;

    public String getName() {

    return name;

    }

    public void setName(String name) {

    this.name = name;

    }

    }

    public class Main {

    public static void main(String[] args){

    Name name1=new Name();

    name1.setName("name1");

    Text t1=new Text();

    t1.setAge(12);

    t1.setName(name1);

    Text t2=(Text) t1.clone();

    System.out.println(t2.getName().getName());

    name1.setName("name2");

    System.out.println(t2.getName().getName());

    }

    }

    输出

    name1

    name2

    结果分析

    因为只是直接调用父类的clone方法,没有对成员属性进行处理,所以在修改t1属性name的值时,t2属性name的值也会随之改变。

    优点

    简单易实现

    缺点

    无法真正克隆对象

    深克隆实现

    通过递归克隆实现

    代码

    public class Text implements Cloneable{

    private int age;

    private Name name;

    public int getAge() {

    return age;

    }

    public void setAge(int age) {

    this.age = age;

    }

    public Name getName() {

    return name;

    }

    public void setName(Name name) {

    this.name = name;

    }

    @Override

    protected Object clone(){

    Text text=null;

    try {

    text=(Text) super.clone();

    } catch (CloneNotSupportedException e) {

    e.printStackTrace();

    }

    text.setName((Name) text.getName().clone());

    return text;

    }

    }

    class Name implements Cloneable{

    private String name;

    public String getName() {

    return name;

    }

    public void setName(String name) {

    this.name = name;

    }

    @Override

    protected Object clone() {

    try {

    return super.clone();

    } catch (CloneNotSupportedException e) {

    e.printStackTrace();

    }

    return null;

    }

    }

    输出

    name1

    name1

    通过序列化实现

    代码

    public class Text implements Serializable{

    private static final long serialVersionUID = 8723901148964L;

    private int age;

    private Name name;

    public int getAge() {

    return age;

    }

    public void setAge(int age) {

    this.age = age;

    }

    public Name getName() {

    return name;

    }

    public void setName(Name name) {

    this.name = name;

    }

    public Object myClone(){

    Text text=null;

    ByteArrayOutputStream bos=new ByteArrayOutputStream();

    try {

    ObjectOutputStream oos=new ObjectOutputStream(bos);

    oos.writeObject(this);

    ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());

    ObjectInputStream ois=new ObjectInputStream(bis);

    text=(Text)ois.readObject();

    } catch (IOException e) {

    e.printStackTrace();

    } catch (ClassNotFoundException e) {

    e.printStackTrace();

    }

    return text;

    }

    }

    class Name implements Serializable {

    private static final long serialVersionUID = 872390113109L;

    private String name;

    public String getName() {

    return name;

    }

    public void setName(String name) {

    this.name = name;

    }

    @Override

    public String toString() {

    return name;

    }

    }

    输出

    name1

    name1

    结果分析

    采用深克隆能有效隔离源对象与克隆对象的联系。

    从实现过程来说,递归克隆存在克隆过程多且复杂的缺点,所以建议采用序列化的方式进行

    深克隆。

    总结

    JAVA对象克隆共有两种形式,三种方法

    浅克隆

    调用clone方法

    深克隆

    递归调用clone方法

    序列化对象

    三种方法之间互有优缺点,具体采用要根据实际情况。

    展开全文
  • 其实在Java中也存在克隆的概念,即实现对象复制。本文将尝试介绍一些关于Java中的克隆和一些深入的问题,希望可以帮助大家更好地了解克隆。假如说你想复制一个简单变量。很简单:int apples = 5;int pears = ...

    克隆,想必大家都有耳闻,世界上第一只克隆羊多莉就是利用细胞核移植技术将哺乳动物的成年体细胞培育出新个体,甚为神奇。其实在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:" + stu1.getNumber());

    System.out.println("学生2:" + stu2.getNumber());

    }

    }

    结果:

    学生1:12345

    学生2:12345

    这里我们自定义了一个学生类,该类只有一个number字段。

    我们新建了一个学生实例,然后将该值赋值给stu2实例。(Student stu2 = stu1;)

    再看看打印结果,作为一个新手,拍了拍胸腹,对象复制不过如此,

    难道真的是这样吗?

    我们试着改变stu2实例的number字段,再打印结果看看:

    stu2.setNumber(54321);

    System.out.println("学生1:" + stu1.getNumber());

    System.out.println("学生2:" + stu2.getNumber());

    结果:

    学生1:54321

    学生2:54321

    这就怪了,为什么改变学生2的学号,学生1的学号也发生了变化呢?

    原因出在(stu2 = stu1) 这一句。该语句的作用是将stu1的引用赋值给stu2,

    这样,stu1和stu2指向内存堆中同一个对象。如图:

    f42f4f6f6d3f671665ce8a6145c965f1.png

    那么,怎样才能达到复制一个对象呢?

    是否记得万类之王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();

    stu1.setNumber(12345);

    Student stu2 = (Student)stu1.clone();

    System.out.println("学生1:" + stu1.getNumber());

    System.out.println("学生2:" + stu2.getNumber());

    stu2.setNumber(54321);

    System.out.println("学生1:" + stu1.getNumber());

    System.out.println("学生2:" + stu2.getNumber());

    }

    }

    结果:

    学生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);

    Student stu2 = (Student)stu1.clone();

    System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());

    System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());

    }

    }

    结果:

    学生1:123,地址:杭州市

    学生2:123,地址:杭州市

    乍一看没什么问题,真的是这样吗?

    我们在main方法中试着改变addr实例的地址。

    addr.setAdd("西湖区");

    System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());

    System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());

    结果:

    学生1:123,地址:杭州市

    学生2:123,地址:杭州市

    学生1:123,地址:西湖区

    学生2:123,地址:西湖区

    这就奇怪了,怎么两个学生的地址都改变了?

    原因是浅复制只是复制了addr变量的引用,并没有真正的开辟另一块空间,将值复制后再将引用返回给新对象。

    所以,为了达到真正的复制对象,而不是纯粹引用复制。我们需要将Address类可复制化,并且修改clone方法,完整代码如下:

    package abc;

    class Address implements Cloneable {

    private String add;

    public String getAdd() {

    return add;

    }

    public void setAdd(String add) {

    this.add = add;

    }

    @Override

    public Object clone() {

    Address addr = null;

    try{

    addr = (Address)super.clone();

    }catch(CloneNotSupportedException e) {

    e.printStackTrace();

    }

    return addr;

    }

    }

    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();

    }

    stu.addr = (Address)addr.clone(); //深度复制

    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);

    Student stu2 = (Student)stu1.clone();

    System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());

    System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());

    addr.setAdd("西湖区");

    System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());

    System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());

    }

    }

    结果:

    学生1:123,地址:杭州市

    学生2:123,地址:杭州市

    学生1:123,地址:西湖区

    学生2:123,地址:杭州市

    这样结果就符合我们的想法了。

    最后我们可以看看API里其中一个实现了clone方法的类:

    java.util.Date:

    /**

    * Return a copy of this object.

    */

    public Object clone() {

    Date d = null;

    try {

    d = (Date)super.clone();

    if (cdate != null) {

    d.cdate = (BaseCalendar.Date) cdate.clone();

    }

    } catch (CloneNotSupportedException e) {} // Won't happen

    return d;

    }

    该类其实也属于深度复制。

    浅克隆和深克隆

    1、浅克隆

    在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

    简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。

    5749140f446d26d9256d63ba7affabb1.png

    在Java语言中,通过覆盖Object类的clone()方法可以实现浅克隆。

    2、深克隆

    在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。

    简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。

    cbedd81526e57b885939007f094be49f.png

    在Java语言中,如果需要实现深克隆,可以通过覆盖Object类的clone()方法实现,也可以通过序列化(Serialization)等方式来实现。

    (如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。)

    序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作。

    扩展

    Java语言提供的Cloneable接口和Serializable接口的代码非常简单,它们都是空接口,这种空接口也称为标识接口,标识接口中没有任何方法的定义,其作用是告诉JRE这些接口的实现类是否具有某个功能,如是否支持克隆、是否支持序列化等。

    解决多层克隆问题

    如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。

    public class Outer implements Serializable{

    private static final long serialVersionUID = 369285298572941L; //最好是显式声明ID

    public Inner inner;

    //Discription:[深度复制方法,需要对象及对象所有的对象属性都实现序列化]

    public Outer myclone() {

    Outer outer = null;

    try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    ObjectOutputStream oos = new ObjectOutputStream(baos);

    oos.writeObject(this);

    // 将流序列化成对象

    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());

    ObjectInputStream ois = new ObjectInputStream(bais);

    outer = (Outer) ois.readObject();

    } catch (IOException e) {

    e.printStackTrace();

    } catch (ClassNotFoundException e) {

    e.printStackTrace();

    }

    return outer;

    }

    }

    Inner也必须实现Serializable,否则无法序列化:

    public class Inner implements Serializable{

    private static final long serialVersionUID = 872390113109L; //最好是显式声明ID

    public String name = "";

    public Inner(String name) {

    this.name = name;

    }

    @Override

    public String toString() {

    return "Inner的name值为:" + name;

    }

    }

    这样也能使两个对象在内存空间内完全独立存在,互不影响对方的值。

    总结

    实现对象克隆有两种方式:

    1). 实现Cloneable接口并重写Object类中的clone()方法;

    2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。

    注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是优于把问题留到运行时。

    以上就是本文关于Java编程实现对象克隆(复制)代码详解的全部内容,希望对大家有所帮助。感兴趣的来朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。

    展开全文
  • Java实现对象深度克隆

    2021-03-07 15:44:56
    实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下 import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io....

    两种方式:
      1). 实现Cloneable接口并重写Object类中的clone()方法;
      2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    public class MyUtil {
    
        private MyUtil() {
            throw new AssertionError();
        }
    
        @SuppressWarnings("unchecked")
        public static <T extends Serializable> T clone(T obj) throws Exception {
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bout);
            oos.writeObject(obj);
    
            ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bin);
            return (T) ois.readObject();
    
            // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
            // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
        }
    }
    class Student implements Cloneable{
        private String name;
        private int age;
        private StudentClass studentClass;
        private List<String> list = new ArrayList<>();
        
        public Student() {
            // TODO Auto-generated constructor stub
            System.out.println("构造方法被调用");
        }
        
        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;
        }
        public StudentClass getStudentClass() {
            return studentClass;
        }
     
     
        public void setStudentClass(StudentClass studentClass) {
            this.studentClass = studentClass;
        }
        
        public void add(String aa){
            this.list.add(aa);
        }
     
     
        @Override
        public Object clone() throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            Student stu = (Student) super.clone();
            
            return stu;
        }
        @Override
        public String toString() {
            return "Student [name=" + name + ", age=" + age + ",class"+studentClass.getStudentClass()+",list"+list+"]";
        }
        
    }

     

    展开全文
  • java对象克隆

    2021-03-11 11:49:07
    java对象克隆简介当我们想要复制一个对象的所有的属性的时候,即创建一个副本,修改副本的中的值时,不会引起原来的对象的值的变化,这时对象克隆非常有用。我们先来看一个简单的例子:创建一个MyUser对象:@Data...
  • 假如说你想复制一个简单变量。很简单:int apples = 5;int pears = apples;...但是如果你复制的是一个对象,情况就有些复杂了。假设说我是一个beginner,我会这样写:classStudent {private intnumbe...
  • 编写我们的实验代码,该代码用于实现我们的一个克隆实例,具体如下图所示,代码如下:public static void main(String[] args) {System.out.println("序列化之前");Address address=new Address("中国","吉林","长春...
  • java如何实现对象克隆

    2021-02-12 09:36:34
    上述方法抛出了一个CloneNotSupportedException异常,如果要实现对象克隆的类没有实现Cloneable接口,则会抛出此异常。但是Cloneable接口没有任何方法,这个是一个标识接口,标识一种操作能力。package ...
  • 如何实现对象克隆 有两种方式: 1)实现Cloneable接口并重写Object类中的clone()方法; 2) 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。 注意:基于序列化和反序列化实现的...
  • Java中如何实现克隆

    2021-03-06 14:23:49
    实现克隆的方法有三种:一、重写clone方法,clone中嵌套clone这种方法的原理其实就是在需要克隆对象以及该对象的引用类型的变量的类中全部实现cloneable接口,否则抛出CloneNotSupportedException将引用类型的...
  • Java-对象克隆

    2021-02-12 23:12:11
    1. 为什么要克隆java中,我们通过直接=等号赋值的方法来拷贝,如果是基本数据类型是没有问题的,例如int i = 1;int j = 0;j = i; // 直接=等号赋值,这样是没有问题的但是如果是引用数据类型,我们拷贝的就是引用...
  • JAVA对象克隆

    2021-02-26 19:55:58
    为什么需要克隆:在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全...克隆实现方式一、浅度克隆对于要克隆对象,对于其基本数据类型的...
  • 关于java对象复制我们在编码过程经常会碰到将一个对象传递给另一个对象,java中对于基本型变量采用的是值传递,...1 对象克隆什么是"clone"?在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中...
  • package ...import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.Arrays;import java.util.List;import com.bin.design.domain....
  • 当一个对象创建过程复杂,我们是否可以根据已有的对象直接来克隆一份,而不必关系创建的细节呢(原型模式)。 1、实现Cloneable接口,重写clone方法 Object默认的clone方法实际是对域的简单拷贝,对于简单数据类型,...
  • java面向对象的编程当中,要复制引用类型的对象,就必须克隆对象。通过调用对所有引用类型和对象都是可用的clone方法,来实现克隆。在Java中传值及引伸深度克隆的思考中,我们讲过引申到克隆技术Java中的所有对象...
  • Java 对象复制

    2021-02-26 10:21:04
    Java 对象的一共有 3 种复制对象的方式。1.直接赋值 (引用复制 ),此种复制方式比较常用。诸如 A a = b ; a 是直接复制了b的引用 ,也就是说它俩指向的是同一个对象。 此时 a == b [ true ] 。1 classA{2 private...
  • [Java教程]JavaScript实现对象克隆函数clone( )的程序及分析0 2014-03-25 13:00:17程序:Object.prototype.Clone = function(){var objClone;if ( this.constructor == Object ) objClone = new this.constructor();...
  • package ...import java.util.ArrayList;import java.util.List;import java.util.function.Consumer;import java.util.function.Supplier;/**** @ClassName: Builder* @Description:* @Auther...
  • Java对象复制三种方式

    千次阅读 2021-02-12 09:36:34
    Java对象复制三种方式概述在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也...
  • java数组对象复制

    2021-02-25 20:06:09
    一、首先,区分数组间的赋值1 importjava.util.Arrays;2 public classArray {3 public static voidmain(String[] args)4 {5 int[] array = new int[]{0, 1, 2, 3};6 int[] arr = array; //书组赋值7 Sys...
  • Java对象克隆详解

    2021-02-13 02:34:37
    原文:http://www.cnblogs.com/Qian123/p/5710533.html假如说你想复制一个简单变量。很简单:int apples = 5;int pears = apples;不仅仅是int类型,其它七...但是如果你复制的是一个对象,情况就有些复杂了。假设说我...
  • 序列化和依次克隆各个可变的引用类型都可以实现克隆,但是序列化的效率并不理想下面是两种实现克隆的实例,并且测试类对两种方法进行了对比:1、重写clone方法使用父类中的clone()方法实现克隆package ...
  • # clone的条件如果你想clone一个对象,就必须满足...Object对象的clone方法是浅克隆,即待克隆对象若存在对象实例域,则仅仅clone其引用。深克隆即clone对象本体。# 实现克隆的方式1. 先使用待克隆对象的clone方...
  • * 问:java如何实现对象克隆? 答:有两种方式: 1)实现Cloneable接口并重写Object类中的clone()方法; 2)实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆, 代码如下。 * */ ...
  • Java里的clone分为:** A:浅复制(浅克隆): **浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。B:深复制(深克隆):深复制把要复制对象所引用的对象复制了一遍。Java对象克隆,为了获取对象的一份拷贝,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 396,339
精华内容 158,535
关键字:

如何实现对象克隆java

java 订阅