当前位置: 代码网 > it编程>编程语言>Java > Java的三个接口Comparable,Comparator,Cloneable(浅拷贝与深拷贝)

Java的三个接口Comparable,Comparator,Cloneable(浅拷贝与深拷贝)

2024年07月28日 Java 我要评论
Java三个接口Comparable、Comparator、Cloneable(浅拷贝和深拷贝)的解析

comparable

当我们要进行对象的比较的时候,我们是不能直接用>、< 这些符号直接进行比较的。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


在object 类中,我们知道可以使用equals方法来进行对象的比较,返回值是布尔值。如果我们要求返回值是整型的话,我们就要使用到comparable接口

使用

class student implements comparable<student>{
    public string name;
    public int age;

    public student(string name, int age) {
        this.name = name;
        this.age = age;
    }

    @override
    public int compareto(student o) {
        return this.age - o.age;
    }
}

我们先来看一下comparable接口:

在这里插入图片描述

comparable接口中包含 compareto,因此我们需要重写这个方法,根据不同的比较需求来写不同的比较代码:
在这里插入图片描述
这里是实现age比较,如果是name比较,我们该怎么实现?

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

多个同类型比较

如果我们有很多个学生需要进行比较排序,我们第一时间会想到使用数组来存放,然后通过数组排序(array.sort())来进行比较排序。

那array.sort 是怎么进行排序的呢?


现在这个类没有comparable接口:
在这里插入图片描述
我们一运行就会发生异常:

在这里插入图片描述
这是是student类不能转化为comparable,说明array.sort的排序需要该类实现comparable接口。

array.sort 会调用 compareto 方法进行比较。


模拟实现array.sort(冒泡排序法)

    public static void mysort(comparable[] comparables) {
        int flag = 1;
        for (int i = 0; flag == 1 && i < comparables.length - 1; i++) {
            flag = 0;
            for (int j = 0; j < comparables.length - 1 - i; j++) {
                if(comparables[j].compareto(comparables[j+1]) > 0) {
                    comparable tmp = comparables[j];
                    comparables[j] = comparables[j+1];
                    comparables[j+1] = tmp;
                    flag = 1;
                }
            }
        }
    }

局限

由于compareto 方法只能重写一次,实现不了重载,因为参数就是所在类的类型(也就意味着这是固定的参数),所以它的局限性就是只能进行一种数值的比较,不能进行多种数值的比较,因此我们一般用在固定的比较,用在默认的比较上,如果要实现不同的数值的比较我们会用到比较器comparator

comparator

我们可以使用comparator实现不同属性比较的类,这里还是以学生类(包括姓名和年龄)作为例子:

public class namecomparator implements comparator<student> {
    @override
    public int compare(student o1, student o2) {
        return o1.name.compareto(o2.name);
    }
}

public class agecomparator implements comparator<student> {
    @override
    public int compare(student o1, student o2) {
        return o1.age - o2.age;
    }
}

之后我们就可以使用这些比较类的方法了,和类的使用是一样的,先创建对象,再使用里面的方法:

    public static void main(string[] args) {
        student stu1 = new student("zhangsan",10);
        student stu2 =new student("lisi",20);

        agecomparator agecomparator = new agecomparator();
        int ret = agecomparator.compare(stu1,stu2);
        system.out.println(ret);

        namecomparator namecomparator = new namecomparator();
        ret = namecomparator.compare(stu1,stu2);
        system.out.println(ret);
    }

如果你需要使用array.sort的话,只需要再传比较类就可以了:

        agecomparator agecomparator = new agecomparator();
        arrays.sort(students,agecomparator);
        
        namecomparator namecomparator = new namecomparator();
        arrays.sort(students,namecomparator);

cloneable

当我们需要进行对象的克隆(复制)的时候,我们可以使用clone的接口,这是object类的,在上一篇文章我们就提到其中的三个方法,现在我们就来将克隆方法(clone)

在这里插入图片描述

使用

在这里插入图片描述

快捷键如下:
在这里插入图片描述
在这里插入图片描述

编译器会帮我们生成如下的代码:

    @override
    protected object clone() throws clonenotsupportedexception {
        return super.clone();
    }

在这里插入图片描述

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

在这里插入图片描述

public static void main(string[] args) throws clonenotsupportedexception{
        student stu1 = new student("zhangsan",14);
        student stu2 = (student)stu1.clone();
    }

但是当我们运行的时候会发现下面的异常:
在这里插入图片描述

在这里插入图片描述

public class student implements cloneable

完成上述步骤我们就可以实现克隆了:

在这里插入图片描述

在这里插入图片描述


以下面的代码为例:
在这里插入图片描述
在这里插入图片描述
我们来克隆一个per1:

person per1 = new person("zhagnsan",10);

浅拷贝示意图:
在这里插入图片描述

深拷贝示意图:
在这里插入图片描述

浅拷贝

通过上面的示意图,我们来做一下题目,说明下面的运行结果:

public class money {
    public double m = 9.99;
}

public class person implements cloneable{
    public string name;
    public int age;

    public 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 +
                ", money=" + money +
                '}';
    }

    @override
    protected object clone() throws clonenotsupportedexception {
        return super.clone();
    }
}

class test{
    public static void main(string[] args) throws clonenotsupportedexception{
        person per1 = new person("zhagnsan",10);
        person per2 = (person) per1.clone();

        per2.money.m = 6.6;
        system.out.println("per1:"+per1.money.m);

        system.out.println("per2:"+per2.money.m);

    }
}

在这里插入图片描述

在这里插入图片描述

这里显而易见,浅拷贝后per1和per2是共享money的,所以有一个人的money发生改变,另一个人的money也会发生改变。

深拷贝

我们知道深拷贝需要再拷贝多一份全新的被包含的对象,所以我们需要实现被包含的对象的拷贝:

public class money implements cloneable{
    public double m = 9.99;

    @override
    protected object clone() throws clonenotsupportedexception {
        return super.clone();
    }
}

这是第一步,下一步我们需要在包含该类的类中的clone方法调用money中的clone方法,才能实现完整的深拷贝工作:

所以我们要修改person中的clone方法:

    @override
    protected object clone() throws clonenotsupportedexception {
        person tmp = (person) super.clone();
        tmp.money= (money) this.money.clone();
        return tmp;
    }

现在再思考一下,下面的代码运行结果是什么?

public class money implements cloneable{
    public double m = 9.99;

    @override
    protected object clone() throws clonenotsupportedexception {
        return super.clone();
    }
}

public class person implements cloneable{
    public string name;
    public int age;

    public 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 +
                ", money=" + money +
                '}';
    }

    @override
    protected object clone() throws clonenotsupportedexception {
        person tmp = (person) super.clone();
        tmp.money= (money) this.money.clone();
        return tmp;
    }
}

class test{
    public static void main(string[] args) throws clonenotsupportedexception{
        person per1 = new person("zhagnsan",10);
        person per2 = (person) per1.clone();

        per2.money.m = 6.6;
        system.out.println("per1:"+per1.money.m);

        system.out.println("per2:"+per2.money.m);

    }
}

在这里插入图片描述

在这里插入图片描述

深拷贝已经重新将money拷贝多一份了,所以per2的money改变了并不会影响到per1的money.

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com