三分钟“手撕”Java中的接口(下)

目录

一、通过接口对引用类型进行排序

1.为什么不直接使用Arrays.sort

2.怎么用接口怎么实现

3.Comparable优点与缺点 

二、Comparator选择器

三、Cloneable接口

四、浅拷贝与深拷贝 

1.浅拷贝

2.深拷贝 


一、通过接口对引用类型进行排序

1.为什么不直接使用Arrays.sort

class Student {
    private String name;
    private int age;
public Student(String name, int age) {
    this.name = name;
    this.age = age;
}
@Override
public String toString() {
    return "[" + this.name + ":" + this.age + "]";
}
}
public class Test {
    public static void main(String[] args) {
       Student[] students = new Student[3];
        student[0] = new Student("zhansgan", 4);
        student[1] = new Student("lisi", 8);
        student[2] = new Student("abbc", 2);
        Arrays.sort(students);
        System.out.println(Arrays.toString(students));
// 运行出错, 抛出异常.
Exception in thread "main" java.lang.ClassCastException: Student cannot be cast to java.lang.Comparable
    }
}

 因为students是引用数据,相当于c语言中的指针。虽说数组也是引用数据,但是数组里面存的都是相同的类型,而students不仅有String还有int类型。系统无法判断你要比较年龄还是名字。

2.怎么用接口怎么实现

这时候就可以用到我们的接口了,让我们的 Student 类实现 Comparable 接口, 并重写其中的 compareTo方法(年龄):

public 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 String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
   @Override
    public int compareTo(Student o) {
        return this.age-o.age;
}
}
public class Test {
    public static void main2(String[] args) {
        Student[] student = new Student[3];
        student[0] = new Student("zhansgan", 4);
        student[1] = new Student("lisi", 8);
        student[2] = new Student("abbc", 2);

        Arrays.sort(student);
        System.out.println(Arrays.toString(student));
    }
}

3.Comparable优点与缺点 

Comparable的优点就是:能够实现引用类型的比较

Comparable的缺点就是:一旦写死,就只能用某一种方法(年龄或者名字等等)比较 

二、Comparator选择器

 那有没有比较灵活一点的比较呢?有那就是Comparator接口

import java.util.Comparator;
import java.util.Arrays;

public class Student {
    public String name;
    public int age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class AgeComparetor implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age- o2.age;
    }
}
public class NameComparetor implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}

public class Test {
    public static void main1(String[] args) {
        Student student1 = new Student("zhansgan", 4);
        Student student2 = new Student("lisi", 8);
//年龄比较选择器
        AgeComparetor ageComparetor=new AgeComparetor();
        int ret1=ageComparetor.compare(student1,student2);
        System.out.println(ret1);
//姓名比较选择器
        NameComparetor nameComparetor=new NameComparetor();
        int ret2=nameComparetor.compare(student1,student2);
        System.out.println(ret2);
    }
}

Comparable接口的出现使得比较可以更加灵活,并且不需要在原来的Student类进行修改,而是直接创造一个AgeComparable或NameComparable的类,需要的时候直接new对象就行了!

三、Cloneable接口

Object 类中存在一个 clone 方法,调用这个方法可以创建一个对象的 "拷贝"。但是要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常

怎么克隆一个引用类型对象?

//类接入Cloneable接口,实现clone功能
class Student implements Cloneable {
    public Money m = new Money();
    public int age;
    public Student(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "money=" + m +
                ", age=" + age +
                '}';
    }
//重写clone方法,右键generate->重写方法->clone()
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test {
//这里牵扯到异常,我后续的博客会讲解
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student(10);
        Student student2 = (Student) student1.clone();
        System.out.println(student2.m.money);
    }
}

 小提示:下列代码这个只有一份,跟拷贝不一样,student2没有生成空间放值,是直接指向student1

Student student2=student1;

四、浅拷贝与深拷贝 

1.浅拷贝

什么是浅拷贝?先让我们看一段代码:

class Money {
    public double money = 12.5;
}
class Student implements Cloneable {
    public Money m = new Money();
    public int age;
    public Student(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "money=" + m +
                ", age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student(10);
        Student student2 = (Student) student1.clone();
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
        student1.m.money = 100;
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
    }
}
//执行结果
12.5
12.5
100.0
100.0

 

 如上代码,我们可以看到,通过clone,我们只是拷贝了Student对象。

但是Student对象中的Money对象,并没有拷贝。

通过studen2这个引用修改了m的值后,studen1这个引用访问m的时候,值也发生了改变。这里就是发生了浅拷贝。

2.深拷贝 

假设我想修改student1中m,不想修改student2中m,这种就是深拷贝,代码实现:

class Money implements Cloneable{
    public double money=12.5;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Student implements Cloneable{
    public Money m=new Money();
    public int age;
    public Student(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "money=" + m +
                ", age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        //return super.clone();
        Student tmp=(Student) super.clone();
        tmp.m=(Money) this.m.clone();
        return tmp;
    }
}
public class FurTest {
    public static void main(String[] args) throws CloneNotSupportedException  {
        Student student1=new Student(10);
        Student student2=(Student) student1.clone();
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
        student2.m.money=100;
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
    }
//执行结果
12.5
12.5
12.5
100.0

 

注意的是:

1.深拷贝需要两种重写clone。一种是studen自己的,一种是money的。 

2.cloneable接口里面什么都没有,它是一个空接口,那为什么还要接入它呢?

答:一个类具备这个特性,才接入的接口。重要的是具不具备。

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值