Cloneable 接口和深拷贝,浅拷贝

目录

一.Cloneable 接口

二.浅拷贝

三.深拷贝

四.comparable接口、

五.comparator接口

1.Java 中内置了一些很有用的接口 , Cloneable 就是其中之一 . Object 中存在一个 clone 方法 , 调用这个方法可以创建一个对象的 " 拷贝 ".
2.来说说调用 clone 方法的注意事项:首先要先 实现Cloneable 接口,然后 重写克隆方法,这里我们会发现, Cloneable 是个空接口,就因为是,空接口才可以被继承。 注意异常,还有向下转型

二.浅拷贝:

如下代码,我们可以看到,通过clone,我们只是拷贝了Person对象。但是Person对象中的Money对象,并没有拷贝。(这里要特别注意:测试类要和,自定义类在同一个包里,clone方法才可以在测试类里,使用)。

代码:

class Money implements Cloneable {
    public double m = 10.9;

    @Override
    protected Object clone()
            throws CloneNotSupportedException {
        return super.clone();
    }

}
public class Person implements Cloneable {
    public String name;
    public int age;
    Money money = new Money();

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    protected Object clone()  //注:谁调用了clone方法,谁就是this(Test中person1调用了clone)
            throws CloneNotSupportedException {
        return super.clone();
       
    }
}


public class Test {
    public static void main(String[] args)
            throws CloneNotSupportedException {
        //浅拷贝
     Person person1 = new Person("lili", 2);
     Person person2 = (Person) person1.clone();
        System.out.println(person2);

        System.out.println("修改前" + person1.money.m);
        System.out.println("修改前" + person2.money.m);

        person2.money.m = 20.9;
        System.out.println("修改后" + person1.money.m);
        System.out.println("修改后" + person2.money.m);
}

画了一个图可以这样理解:这里结果反应了浅拷贝

三.深拷贝:我们可以看到,通过clone,我们既拷贝Person对象。这里注意:(我们通过,persion1对象money的引用,来克隆(不要忘记向下转型)。

)拷贝Person对象中的Money对象,并没有拷贝。

代码如下:

class Money implements Cloneable {
    public double m = 10.9;

    @Override
    protected Object clone()
            throws CloneNotSupportedException {
        return super.clone();
    }

}
public class Person implements Cloneable {
    public String name;
    public int age;
    Money money = new Money();

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    protected Object clone()  //注:谁调用了clone方法,谁就是this(Test中person1调用了clone)
            throws CloneNotSupportedException {
        Person tmp = (Person)super.clone();
        tmp.money = (Money)this.money.clone();//通过对象(.)引用(.)克隆(通过引用修改)
         return tmp;
    }
}




public class Test {
    public static void main(String[] args)
            throws CloneNotSupportedException {

        //深拷贝
        Person person1 = new Person("lili", 2);
        Person person2 = (Person) person1.clone();
        System.out.println(person2);

        System.out.println("修改前" + person1.money.m);
        System.out.println("修改前" + person2.money.m);

        person2.money.m = 20.9;
        System.out.println("修改后" + person1.money.m);
        System.out.println("修改后" + person2.money.m);
    }
}

 这是我对深拷贝的理解:结果反应深拷贝

四.comparable接口:

1.使用:涉及到自定义类型比较可以用,comparable接口:

2.实现接口并重写compareTo方法,注意:泛型哪里,计较哪个对象就写,哪个对象,还有这里我们自己,写了一个排序方法,通过sort,调用compareTo方法,我们会传入Student对象,这里this和O,是我们,比较的学生对象。

3.这里我们自己模拟了,被调接口里的排序方法(我们默认升序写法)。当然也可以用,接口本来比较,复杂的方法。

通过传入,接口来规范我们,达到,不同对象都可以用的,作用

public static void mySort(Comparable[] comparable) {  //这里用接口类型的数组接受,只要接口里有对应的方法,就可以通过实例化,这个接口类型的数组,来调用对应方法
        for (int i = 0; i < comparable.length-1; i++) {
            for (int j = 0; j < comparable.length-1-i; j++) {
                /**
                 * 注意:数组是引用类型(相当于地址),不可以这样比较(comparable[j] > comparable[j+1])
                 */

                if (comparable[j].compareTo(comparable[j+1]) > 0) {
                    Comparable tmp = comparable[j];
                    comparable[j] = comparable[j+1];
                    comparable[j+1] = tmp;
                }
            }
        }
    }

下面给代码现象:

4.这个接口,也有缺陷,比较较为固定(要自己单独更换,重写方法,里的比较方式),接下来我们换一个接口。

五.comparator接口:(这个接口,我们可以单独,自己写一类,也就是一个比较器):可以达到解耦的目的,很方便。解耦就是(有一个锁,需要两把钥匙才可以打开,而这两把钥匙则都在你手上,而不是你手里只有一把

1.使用:这里排序方法还是用我们自己写的

2.重写compare方法:(这里我们的,NameComparator就是,一个比较器,为什么呢?就是我们这里规定,自定义Name来比较。) 

注意:这里比较Name时候可以使用ComparTo方法因为String类型本来就实现了Comparable接口,使用可以使用Comparable里的compareTo方法。

main方法里的代码:

public static void main(String[] args) {
        NameComparator nameComparator = new NameComparator();

        Student[] student =  new Student[3];
        student[0] = new Student("wada", 8);
        student[1] = new Student("lili", 9);
        student[2] = new Student("huahua", 10);


        System.out.println("排序前" + Arrays.toString(student));


        Arrays.sort(student, nameComparator);//这里要,多传一个,构造器对象
        System.out.println("排序后" + Arrays.toString(student));



    }

结果:

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

robin_suli

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值