Java 对象克隆

首先,我们需要知道的是,什么是对象克隆?对象克隆是当程序运行时,可能需要一个新对象,用来保存当前对象的状态,并且新的对象与当前对象没有任何关联,即我改变了新对象属性的值,而当前对象没有发生改变。而这新的对象,就是对当前对象的克隆,或者说拷贝。

要完成对象克隆,有以下要求:

 1. 新的对象与当前对象值相同

2. 新的对象与当前对象的引用地址不同

要实现对象克隆,有以下步骤:

  1. 对要被对象克隆的对应类继承Cloneable接口,并重载clone方法,将访问权限改成public

2. 将当前对象的clone方法赋值给新的对象,完成对象克隆。

public class Test  implements Cloneable{
    public int a;
    public int b;
    private int c;
    private int d;
    public String aa;
    private String bb;
    public TestIn testIn = new TestIn();
    public TestIns testIns = new TestIns();

    @Override
    public Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }

    public Test(){}
    public Test(int a,int b,int c,int d){
        this.a=a;
        this.b=b;
        this.c=c;
        this.d=d;
    }
    private Test(int c,int d){
        this.c=c;
        this.d=d;
    }

    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
    public int getB() {
        return b;
    }
    public void setB(int b) {
        this.b = b;
    }
    public int getC() {
        return c;
    }
    public void setC(int c) {
        this.c = c;
    }
    public int getD() {
        return d;
    }
    public void setD(int d) {
        this.d = d;
    }
    private void A(){
        System.out.println("哈哈哈");
    }
    public void B(){
        System.out.println("fdsa");
    }

    public String getAa() {
        return aa;
    }

    public void setAa(String aa) {
        this.aa = aa;
    }

    public String getBb() {
        return bb;
    }

    public void setBb(String bb) {
        this.bb = bb;
    }

    @Override
    public String toString() {
        return "Test [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + ", aa=" + aa + ", bb=" + bb + "]";
    }

    class TestIn{
        public String test_a;
        public int test_b;
    }
    class TestIns{
        public String test_a;
        public int test_b;
    }
}
Test test_1 = new Test();Test test_2 = (Test) test_1.clone();
System.out.println("\r++++++++++拷贝(克隆)+++++++++++");
System.out.println("----------赋值前----------");
System.out.println("test_1:"+test_1);
System.out.println("test_2:"+test_2);

test_2.setA(4);
System.out.println("----------赋值基本类型----------");
System.out.println("test_1:"+test_1);
System.out.println("test_2:"+test_2);System.out.println("类是否引用同个地址:"+(test_1 == test_2));

以上代码的运行结果为:

++++++++++拷贝(克隆)+++++++++++
----------赋值前----------
test_1:Test [a=2, b=0, c=0, d=0, aa=null, bb=null]
test_2:Test [a=2, b=0, c=0, d=0, aa=null, bb=null]
----------赋值基本类型----------
test_1:Test [a=2, b=0, c=0, d=0, aa=null, bb=null]
test_2:Test [a=4, b=0, c=0, d=0, aa=null, bb=null]
类是否引用同个地址:false

这样,我们就实现了对象的克隆,当然,仅仅只是针对当前对象基本类型的克隆,这种对象克隆我们称之为浅克隆。

而如果要实现基本数据类型以及引用类型的克隆,就需要深克隆。

在test类中,你们也可以看到,有两个类的对象,一个是TestIn类,一个是TestIns类,并且都初始化了,然而在浅克隆的情况下,他们指向的地址是一致的

System.out.println("类的引用类TestIn是否引用同个地址:"+(test_1.testIn == test_2.testIn));
System.out.println("类的引用类TestIns是否引用同个地址:"+(test_1.testIns == test_2.testIns));

其运行结果:

类的引用类TestIn是否引用同个地址:true
类的引用类TestIns是否引用同个地址:true

如何实现深克隆呢,其实实现深克隆和实现浅克隆的原理差不多,步骤如下:

  1.被克隆的对象对应类要继承Cloneable接口,并重载clone方法

2.若被克隆的对象里,有属性为被克隆的对象,则需要重写clone方法

3. 将当前对象的clone方法赋值给新的对象,完成对象深克隆。

以下代码我重写了Test的clone方法,并让对应类TestIns继承了Cloneable接口,重载clone方法

public class Test  implements Cloneable{
    public int a;
    public int b;
    private int c;
    private int d;
    public String aa;
    private String bb;
    public TestIn testIn = new TestIn();
    public TestIns testIns = new TestIns();

    @Override
    public Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        Test test = (Test)super.clone();
        test.testIns =(TestIns) this.testIns.clone();
        return test;
    }

    public Test(){}
    public Test(int a,int b,int c,int d){
        this.a=a;
        this.b=b;
        this.c=c;
        this.d=d;
    }
    private Test(int c,int d){
        this.c=c;
        this.d=d;
    }

    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
    public int getB() {
        return b;
    }
    public void setB(int b) {
        this.b = b;
    }
    public int getC() {
        return c;
    }
    public void setC(int c) {
        this.c = c;
    }
    public int getD() {
        return d;
    }
    public void setD(int d) {
        this.d = d;
    }
    private void A(){
        System.out.println("哈哈哈");
    }
    public void B(){
        System.out.println("fdsa");
    }

    public String getAa() {
        return aa;
    }

    public void setAa(String aa) {
        this.aa = aa;
    }

    public String getBb() {
        return bb;
    }

    public void setBb(String bb) {
        this.bb = bb;
    }

    @Override
    public String toString() {
        return "Test [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + ", aa=" + aa + ", bb=" + bb + "]";
    }

    class TestIn{
        public String test_a;
        public int test_b;
    }
    class TestIns implements Cloneable{
        public String test_a;
        public int test_b;

        @Override
        protected Object clone() throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            return super.clone();
        }
    }
}
System.out.println("类的引用类TestIn是否引用同个地址:"+(test_1.testIn == test_2.testIn));
System.out.println("类的引用类TestIns是否引用同个地址:"+(test_1.testIns == test_2.testIns));

运行效果如下:

类的引用类TestIn是否引用同个地址:true
类的引用类TestIns是否引用同个地址:false

有兴趣的可以去了解一下,为什么克隆有浅克隆和深克隆的区别:https://www.jianshu.com/p/b597f3e8269a

总结:无论是浅克隆还是深克隆,都需要将对应类继承Cloneable接口,并重载或者重写clone方法;浅克隆,只能克隆类的基本类型,而深克隆则可以克隆基本基本类型以及引用类型。

public class TestMain{
    public static void main(String[] args){
        Test test_1 = new Test();
        Test test_2 = test_1;
        System.out.println("++++++++++引用+++++++++++");
        System.out.println("----------赋值前----------");
        System.out.println("test_1:"+test_1);
        System.out.println("test_2:"+test_2);

        test_2.setA(2);
        System.out.println("----------赋值后----------");
        System.out.println("test_1:"+test_1);
        System.out.println("test_2:"+test_2);
        System.out.println("类是否引用同个地址:"+(test_1 == test_2));

        try {
            test_2 = (Test) test_1.clone();
            System.out.println("\r++++++++++拷贝(克隆)+++++++++++");
            System.out.println("----------赋值前----------");
            System.out.println("test_1:"+test_1);
            System.out.println("test_2:"+test_2);

            test_2.setA(4);
            System.out.println("----------赋值基本类型----------");
            System.out.println("test_1:"+test_1);
            System.out.println("test_2:"+test_2);
            System.out.println("类是否引用同个地址:"+(test_1 == test_2));
            System.out.println("类的引用类TestIn是否引用同个地址:"+(test_1.testIn == test_2.testIn));
            System.out.println("类的引用类TestIns是否引用同个地址:"+(test_1.testIns == test_2.testIns));
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

原文地址:https://www.cnblogs.com/hjlin/p/11368289.html

时间: 2024-08-13 17:45:42

Java 对象克隆的相关文章

Java对象克隆了解

1.java接口中有一种空的接口叫标识接口,这种接口值起到标识作用. 2.要实现java对象克隆需要用到Object类的 protected Object clone() throws CloneNotSupportedException    方法,这个方法为protected限定,在本包中,或者不同包的子类中才能访问,并且抛出异常. 3.如果要实现对象克隆首先被克隆的类必须实现Cloneable接口,如果没有实现这个接口,调用clone()方法会抛出 CloneNotSupportedExc

Java对象克隆(Clone)及Cloneable接口、Serializable接口的深入探讨

Java对象克隆(Clone)及Cloneable接口.Serializable接口的深入探讨 Part I 没啥好说的,直接开始Part II吧. Part II 谈到了对象的克隆,就不得不说为什么要对对象进行克隆.Java中所有的对象都是保存在堆中,而堆是供全局共享的.也就是说,如果同一个Java程序的不同方法,只要能拿到某个对象的引用,引用者就可以随意的修改对象的内部数据(前提是这个对象的内部数据通过get/set方法曝露出来).有的时候,我们编写的代码想让调用者只获得该对象的一个拷贝(也

Java对象克隆

Java不提供克隆(复制)对象的自动机制.克隆对象意味着逐位复制对象的内容.要支持克隆操作,请在类中实现clone()方法.Object类中的clone()方法的声明如下: 1 protected  Object clone()  throws   CloneNotSupportedException clone()方法声明为protected. 因此,不能从客户端代码调用它.以下代码无效: 1 2 Object obj  = new Object(); Object clone = obj.c

java对象的克隆

java对象克隆方式主要有两种:浅克隆和深克隆 首先,不要把对象的克隆和对象的赋值搞混了,看下图 p2 = p1;就是赋值操作,赋值操作只是让被赋值对象指向之前对象的地址,实际上的物理内存是一块,而克隆操作的结果应该是两个对象分别指向内容相同的两块内存.如下就是克隆操作后的状态: 下面说浅克隆和深克隆: 深克隆和浅克隆的区别主要出现在类里有外部类对象时,如下,Person类中有Address类的对象 1 package cn.itcast.copy; 2 3 import java.io.Ser

Java提高篇——对象克隆(复制)

阅读目录 为什么要克隆?如何实现克隆浅克隆和深克隆解决多层克隆问题总结 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况. 但是如果你复制的是一个对象,情况就有些复杂了. 假设说我是一个beginner,我会这样写: class Student { private int number; pu

Java对象和集合的拷贝/克隆/复制

昨天同事遇到了一个奇怪的问题,他需要将一个JavaBean拷贝一份,然后对新创建的Bean进行操作.但是他对新的Bean操作后,会影响旧的Bean的值.当听到这个问题的时候,我第一反应就是他的拷贝方法有问题,只是将aBean的内容复制给了bBean,但是在内存中指向的是同一个地址.这里就引出了两个关键词,浅拷贝和深拷贝. 浅拷贝(浅克隆) 被复制对象的所有变量值都和原来的对象的值相同,但是复制后的对象的引用仍然指向原来的对象.简单来说,就是对A进行拷贝生成B,只是将A的值复制给了B,内存中指向的

[Java学习笔记]对象克隆

对象克隆: 浅克隆: 被克隆的对象中的值类型数据被复制一份新值,但是引用的对象只被复制其引用传递给新克隆出来的对象 深克隆: 被克隆的对象中的值类型数据被复制一份新值,并且其中引用的对象会重新创建新的对象,把新对象的引用传递给新克隆出来的对象 Java中实现克隆: Java中Object中定义了clone方法,默认为浅克隆操作,即你只是简单super.clone得到的结果是浅克隆的结果,如果需要深克隆,则需要实现Cloneable接口,并且重写clone方法 查看Java源代码发现Object中

JAVA对象任意深度克隆clone工具类分享

原文:JAVA对象任意深度克隆clone工具类分享 源代码下载地址:http://www.zuidaima.com/share/1550463408114688.htm package com.zuidaima.n_app.util; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import jav

java对象的深浅克隆

package CloneTest; class Dog implements Cloneable{ private String dname; private Integer dage; public Dog clone() throws CloneNotSupportedException{  Dog cloned=(Dog) super.clone();  return cloned;   } public String getDname() {  return dname; } publ