Thinking in java自读笔记:传递对象与克隆

前提:对于常规数据类型而言,可以分为值类型和引用类型,值类型为我们常说的”主类型”,”值类型”直接将内存存储在栈内,由系统自动释放资源的数据类型;引用类型是由类型的实际值引用(类似于指针)表示的数据类型,即一个在栈上的引用指向一个在堆上的实例的类型。

一.值的传递

当将应用类型和值类型作为参数进行传递时,会制作一个本地副本(引用类型我认为也是有一个副本,只不过是引用的副本),以下为2种情形:
1.值类型传递
public void f(int b);
这里写图片描述
因此值类型传值在方法体内对b的操作不会影响到a的值
2.引用类型传递
public void f(Object b)
这里写图片描述
因此引用类型传值在方法体内对b的操作会影响到a的值,但只能改变值,不能改变引用关系,如b=null,这时a并不等于null,这个操作只是将b指向空,a依旧指向a的实例。

二.对象的克隆

对象要具备克隆能力,必须实现Cloneable接口,这个接口不含任何方法,它只是一个标识,表明这个类型的对象具备克隆能力,在具备克隆能力之后,还得重写clone()方法,将之覆盖为public。对象的克隆分为“浅层次克隆”于”深层次克隆”。以下为普通对象和合成对象的测试。
1.普通对象的克隆

public class Test {
    public static void main(String[] args) throws  CloneNotSupportedException{
        Student a=new Student("Lz");
        Student b=a.clone();
        b.name="Qy";
        System.out.println(a.hashCode()+a.name);
        System.out.println(b.hashCode()+b.name);
    }
}
class Student implements Cloneable
{
    String name;
    Student(String name)
    {
        this.name=name;
    }

    @Override
    public Student clone() throws CloneNotSupportedException {
        Student o=null;
        o=(Student) super.clone();
        return o;
    }
}

这是最简单的克隆情况,输出2个对象的名字和hashCode(),发现名字和hashCode()都是不一样,这是2个不同的对象。
2.合成对象的“浅层次”克隆

public class Test {
    public static void main(String[] args) throws  CloneNotSupportedException{
        MyClass classOne=new MyClass();
        MyClass classTwo=classOne.clone();
        System.out.println(classOne.hashCode());
        System.out.println(classTwo.hashCode());

        classOne.a.name="QE";
        System.out.println(classTwo.a.name);

        System.out.println(classOne.a.hashCode());
        System.out.println(classTwo.a.hashCode());
    }
}
class MyClass implements Cloneable
{
    Student a=new Student("Lz");
    Student b=new Student("Qy");

    @Override
    public MyClass clone() throws CloneNotSupportedException {
        MyClass o=null;
        o=(MyClass) super.clone();
        return o;
    }
}
class Student implements Cloneable
{
    String name;
    Student(String name)
    {
        this.name=name;
    }

    @Override
    public Student clone() throws CloneNotSupportedException {
        Student o=null;
        o=(Student) super.clone();
        return o;
    }
}

输出结果:
这里写图片描述
从结果中,可以发现classOne和classTwo是2个不同的对象,它们的hashCode()不同,改变classOne.a.name的值,classTwo.a.name的值也跟着改变,且它们的hashCode()相同,它们是同一个对象。这是为什么呢?这就是”浅层次复制”,即只复制了对象的表面,它的内部对象并没有改变。
3.合成对象的“深层次克隆”
将Myclass类的clone()方法改成下面这样:

    @Override
    public MyClass clone() throws CloneNotSupportedException {
        MyClass o=null;
        o=(MyClass) super.clone();
        o.a=a.clone();
        o.b=b.clone();
        return o;
    }

在clone()里面,手动调用内部对象的克隆方法,将表面对象的内部对象引用分别指向内部对象clone()方法返回的对象。

猜你喜欢

转载自blog.csdn.net/qq_27368993/article/details/82699680