当前位置:   article > 正文

Java中浅拷贝与深拷贝_java int 深拷贝

java int 深拷贝

Java的深浅拷贝 或者 复制

1.基本类型之间的拷贝如:

			int apples = 5;
			int pears = apples;
  • 1
  • 2

不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short,float,double,long)同样适用于该类情况,其实就是赋值。但是如果你复制的是一个对象,情况就有些复杂了。

2.异常现象:
创建一个类:

		@Data
		public class GoodStudent{
		    private String classNum;
		}
  • 1
  • 2
  • 3
  • 4

创建一个测试类:

 @Test
    public void test01() {
        GoodStudent goodStudent1 = new GoodStudent();
        GoodStudent goodStudent2 = goodStudent1;
        /**
         * 输出结果:
         * GoodStudent(classNum=11)
         * GoodStudent(classNum=11)
         * 原因是:
         *          上面是将new GoodStudent()对象的引用给了goodStudent2,
         *          然后改了goodStudent2,goodStudent1也就跟着一起变
         */
        goodStudent2.setClassNum("11");
        System.out.println(goodStudent1);
        System.out.println(goodStudent2);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

测试结果:

		GoodStudent(classNum=11)
        GoodStudent(classNum=11)
  • 1
  • 2

为什么改动了goodStudent2 ,而goodStudent1也跟着一起改动呢,原来是

		GoodStudent goodStudent2 = goodStudent1;
  • 1

只是将goodStudent1引用的对象赋给了goodStudent2,复制的只是对象引用,所有改动goodStudent2,本会就是改动了引用的对象,所以goodStudent1也会改变!
goodStudent1和goodStudent2 指向内存堆中同一个对象
那么如果不想让goodStudent1 也改变应该怎样做呢?这就要了解对象的拷贝了:

3.浅拷贝:
那么,怎样才能达到复制一个对象呢?
是否记得万类之王Object。它有11个方法,有两个protected的方法,其中一个为clone方法。
该方法的签名是:
protected native Object clone() throws CloneNotSupportedException;
因为每个类直接或间接的父类都是Object,因此它们都含有clone()方法,但是因为该方法是protected,所以都不能在类外进行访问。
要想对一个对象进行复制,就需要对clone方法覆盖。
步骤:
1.新建一个实体类,里面重写了clone() 方法,必须要实现Cloneable接口

@Data
public class GoodStudent implements Cloneable {
    private String classNum;

    public Object clone() {
        GoodStudent stu = null;
        try{
            stu = (GoodStudent)super.clone();
        }catch(CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return stu;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2.新建测试类:

 	@Test
    public void test02() throws CloneNotSupportedException {

        GoodStudent stu1 = new GoodStudent();
        stu1.setClassNum("1");
        /**
         * 这是浅拷贝 调用的是GoodStudent里面对clone方法的重写
         */
        GoodStudent stu2 = (GoodStudent)stu1.clone();
        System.out.println("好学生1:" + stu1.getClassNum());
        System.out.println("好学生2:" + stu2.getClassNum());
        stu2.setClassNum("2");
        System.out.println("好学生1:" + stu1.getClassNum());
        System.out.println("好学生2:" + stu2.getClassNum());
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

输出结果如下:

好学生1:1
好学生2:1
好学生1:1
好学生2:2
  • 1
  • 2
  • 3
  • 4

这样就实现了 对 对象的浅拷贝。问题又来了,如果GoodStudent中又有一个对象引用 比如 private Address address,如下代码所示,如果继续使用上面的复制方法,使类实现Cloneable接口,重写protected修饰的clone() 方法,但是里面的Address对象没有实现Cloneable接口,复制的时候,也只是复制的是对象的引用,难道让Address也要实现Cloneable接口吗,如果里面有十个八个对象呢,难道每个都需要吗,如果引用的是第三方的对象又该如何呢?

@Data
public class GoodStudent implements Cloneable {

	private Address address;
	
    private String classNum;

    public Object clone() {
        GoodStudent stu = null;
        try{
            stu = (GoodStudent)super.clone();
        }catch(CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return stu;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

如果进行上面的操作就是浅拷贝,那如何进行深拷贝呢?

4.深拷贝:
新建一个类:

@Data
public class Dog implements Serializable {
    private String dogName;
}

  • 1
  • 2
  • 3
  • 4
  • 5

再建一个类并引用Dog对象:

@Data
public class Animal implements Serializable {
    private String name;
    private Dog dog;
}
  • 1
  • 2
  • 3
  • 4
  • 5

这两个类都实现Serializable接口:(必须要实现)

再建一个实现深拷贝的接口实现类:

public class ObjCloner {
    @SuppressWarnings("unchecked")
    public static  <T>T cloneObj(T obj){
        T retVal = null;
        try{
            // 将对象写入流中
            ByteArrayOutputStream ins = new ByteArrayOutputStream();
            ObjectOutputStream inos = new ObjectOutputStream(ins);
            inos.writeObject(obj);
            // 从流中读出对象
            ByteArrayInputStream outs = new ByteArrayInputStream(ins.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(outs);
            retVal = (T)ois.readObject();
        }catch(Exception e){
            e.printStackTrace();
        }
        return retVal;
    }
    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

测试类:

	@Test
    public void test03(){
        Animal animal = new Animal();
        animal.setName("大象");
        Dog dog = new Dog();
        dog.setDogName("小狗");
        animal.setDog(dog);
        Animal animal1 = ObjCloner.cloneObj(animal);
        System.out.println("动物的名称:"+animal.getName()+"  狗的名称:" 
        						+ animal.getDog().getDogName());
        System.out.println("克隆后动物名称:"+animal1.getName()+"  克隆后狗的名称:" 
        						+ animal1.getDog().getDogName());
        System.out.println(" ----------------------------------------------------------");
        animal1.setName("狮子");
        animal1.getDog().setDogName("小狗狗");
        System.out.println("动物的名称:"+animal.getName()+"  狗的名称:" 
        						+ animal.getDog().getDogName());
        System.out.println("克隆后动物名称:"+animal1.getName()+"  克隆后狗的名称:" 
        						+ animal1.getDog().getDogName());
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

打印结果如下:

动物的名称:大象  狗的名称:小狗
克隆后动物名称:大象  克隆后狗的名称:小狗
 ---------------------------------------------------------------------------------------
动物的名称:大象  狗的名称:小狗
克隆后动物名称:狮子  克隆后狗的名称:小狗狗
  • 1
  • 2
  • 3
  • 4
  • 5

这就实现了,Java对象的复制,也就是深浅拷贝

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/616646
推荐阅读
相关标签
  

闽ICP备14008679号