Java的Comparable,Comparator和Cloneable三大接口详解

目录
  • 1、比较器
    • 1.1Comparable接口
    • 1.2Comparator接口
  • 2、Cloneable接口
    • 2.1深拷贝和浅拷贝
  • 总结

1、比较器

①比较器的引入

a.首先,当我们单一地比较某一种数据类型的数组时,可以直接用Arrays.sort()进行实现

b.而当我们同时含有多个参数时,并没有告诉我们按照什么来进行排序,此时,若是用Arrays.sort()就会出现报错的情况

 基于这种情况,我们了解到,若是要将自定义类型进行大小比较 ,就要引入能够实现比较的接口,下面我们介绍Comparable和Comparator这两种比较器

1.1Comparable接口

①实现Comparable接口的操作

②通过Comparable接口实现年龄的排序

③通过Comparable来实现名字的排序(注意名字是引用类,比较时应该是用compareTo()来进行)

④升序降序

由于最终是利用的Arrays.sort()进行的比较,该方法底层是升序的操作,若是想转换为降序,只需要将重写的compareTo()方法中两项互换位置即可

变为降序后代码运行结果:

 ⑤缺点!!!

Comparable对类的倾入性很强。由上面我们可知,要想比较新的类型就要更改compareTo()中的类型重新进行比较,这个在以后的工作中极大可能会使整个代码出现逻辑问题,可读性问题,因此我们引入下一类很灵活,倾入性不强的Comparator接口

⑥整体代码如下:

import java.util.Arrays;
class Student implements Comparable<Student> {
    public int age;
    public String name;
    public double score;
    public Student(int age,String name,double score){
        this.age=age;
        this.name=name;
        this.score=score;
    }
     @Override
     public String toString() {
         return "Student{" +
                 "age=" + age +
                 ", name='" + name + '\'' +
                 ", score=" + score +
                 '}';
     }
    public static void main3(String[] args) {
        Student student1=new Student(12,"张三",98.0);
        Student student2=new Student(18,"李四",97.9);
        //if(student1.compareTo(student2)>0)返回1;根据下面的方法进行进一步的返回
        System.out.println(student1.compareTo(student2));
    }
    public static void main(String[] args) {
        Student []student=new Student[3];
        student[0]=new Student(36,"zhangsan",98.0);
        student[1]=new Student(18,"lisi",97.9);
        student[2]=new Student(27,"wangwu",65.3);
        System.out.println(Arrays.toString(student));
        Arrays.sort(student);
        System.out.println(Arrays.toString(student));
    }
     public static void main1(String[] args) {
         int []array=new int []{2,5,3,6,8};
         System.out.println(Arrays.toString(array));
         Arrays.sort(array);
         System.out.println(Arrays.toString(array));
     }
    @Override
//谁调用这个方法,谁就是this
    public int compareTo(Student o) {
    //return this.age-o.age;
    return o.name.compareTo(this.name);
    }
}

1.2Comparator接口

①实现Comparable接口的操作:

②通过该接口实现的姓名的比较:

③升序降序

执行后的结果: 

④优点

灵活,对类的倾入性不强

⑤整体代码如下:

import java.util.Arrays;
import java.util.Comparator;
class Student {
    public int age;
    public String name;
    public double score;
    public Student(int age, String name, double score) {
        this.age = age;
        this.name = name;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}
class AgeComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age-o2.age;
    }
}
class ScoreComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return (int)(o1.score-o2.score);
    }
}
class NameComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}
public class Test {
    public static void main2(String[] args) {
        Student students1 = new Student(1,"bit",98.9);
        Student students2 = new Student(2,"abc",88.9);
       /* if(students1.compareTo( students2) > 0) {
        }*/
        //System.out.println(students1.compareTo( students2));
        AgeComparator ageComparator = new AgeComparator();
        System.out.println(ageComparator.compare(students1,students2));
    }
    public static void main(String[] args) {
        Student[] student = new Student[3];
        student[0] = new Student(12,"lisi",98.9);
        student[1] = new Student(6,"zangwu",88.9);
        student[2] = new Student(18,"whangsan",18.9);
        System.out.println(Arrays.toString(student));
        AgeComparator ageComparator = new AgeComparator();
        ScoreComparator scoreComparator = new ScoreComparator();
        NameComparator nameComparator = new NameComparator();
        Arrays.sort(student,nameComparator);//默认是从小到大的排序
        System.out.println(Arrays.toString(student));
    }
    public static void main1(String[] args) {
        int[] array = {1,21,3,14,5,16};
        System.out.println(Arrays.toString(array));
        Arrays.sort(array);
        System.out.println(Arrays.toString(array));
    }
}

2、Cloneable接口

①如何实现Cloneable接口:

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

a.实现Cloneable接口

b.重写Cloneable方法

c.抛异常,强制类型转换

②面试中常问问题:

你知道Cloneable接口吗?为什么它是一个空接口,它有什么作用呢?

空接口,标志接口,代表这个类是可以被克隆的

③克隆的原理图:

④整体代码的实现:

class Person implements Cloneable{
    public int age;
    public void eat(){
        System.out.println("吃!");
    }
    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person();
        person.age=13;
        Person person2=(Person)person.clone();
        System.out.println(person2);
        System.out.println(person);
        System.out.println("===========");
        person2.age=14;
        System.out.println(person);
        System.out.println(person2);
    }
}

2.1深拷贝和浅拷贝

①深浅拷贝:

决定是深拷贝还是浅拷贝,并不是方法的用途,而是代码的实现

②浅拷贝示例

浅拷贝代码如下:

class Money implements Cloneable{
    public double m = 12.5;
}
class Person implements Cloneable{
    public int age;
    public Money money = new Money();
    public void eat() {
        System.out.println("吃!");
    }
    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person)super.clone();
        return tmp;
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person();
        Person person2 = (Person)person.clone();
        System.out.println(person.money.m);
        System.out.println(person2.money.m);
        System.out.println("=====================");
        person2.money.m = 98.5;
        System.out.println(person.money.m);
        System.out.println(person2.money.m);
    }
}

③深拷贝示例:(将tmp中的money也进行拷贝)

深拷贝代码如下:

class Money implements Cloneable{
    public double m = 12.5;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    public int age;
    public Money money = new Money();
    public void eat() {
        System.out.println("吃!");
    }
    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person)super.clone();
        tmp.money = (Money) this.money.clone();
        return tmp;
        //return super.clone();
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person();
        Person person2 = (Person)person.clone();
        System.out.println(person.money.m);
        System.out.println(person2.money.m);
        System.out.println("=====================");
        person2.money.m = 98.5;
        System.out.println(person.money.m);
        System.out.println(person2.money.m);
    }
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Java的深拷贝与浅拷贝的几种实现方式

    1.介绍 关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象.可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传递或者引用传递将会有更深的理解. 2.浅拷贝 浅拷贝就是获得拷贝对象的引用,而不是正真意义上的拷贝一个对象,例如 A a = new A(); A b = a; 此时引用变量a和b 同时指向了同一个堆中的内存空间,变量b只是复制了实例A的引用地址,并不是重新在堆中开辟了一个新的空间位置,来完整的复制

  • JavaSE的三大接口:Comparator,Comparable和Cloneable详解

    进阶JavaSE-三大接口:Comparator.Comparable和Cloneable. Comparable和Comparator这两个接口很相似,都是用于比较大小的接口.在我们写一些数据结构的算法题时,用的比较多,具体是怎么用的,我们接着往下看. Comparator接口: public interface Comparator<T> { public int compare(T o1, T o2); //比较方法 } Comparable接口: public interface Co

  • Java的深拷贝和浅拷贝深入了解

    关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象.可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传递或者引用传递将会有更深的理解. 1.创建对象的5种方式 ①.通过 new 关键字 这是最常用的一种方式,通过 new 关键字调用类的有参或无参构造方法来创建对象.比如 Object obj = new Object(); ②.通过 Class 类的 newInstance() 方法 这种默认是调用类的无参构

  • Java Clone深拷贝与浅拷贝的两种实现方法

    1.首先,你要知道怎么实现克隆:实现Cloneable接口,在bean里面重写clone()方法,权限为public. 2.其次,你要大概知道什么是地址传递,什么是值传递. 3.最后,你要知道你为什么使用这个clone方法. 先看第一条,简单的克隆代码的实现.这个也就是我们在没了解清楚这个Java的clone的时候,会出现的问题. 看完代码,我再说明这个时候的问题. 先看我要克隆的学生bean的代码: package com.lxk.model; /** * 学生类:有2个属性:1,基本属性-S

  • Java中浅拷贝和深拷贝详解

    目录 Java浅拷贝深拷贝 实现浅拷贝 实现深拷贝 Java浅拷贝深拷贝 浅拷贝和深拷贝涉及到了Object类中的clone()方法 实现浅拷贝 浅拷贝的实现需要类重写clone()方法 浅拷贝会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝 如果属性是基本类型,拷贝的就是基本类型的值: 如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象,导致两个对象的引用不等. 实现浅拷贝很简单只需要将类实现Cloneable接口然后重写c

  • Java Cloneable接口的深拷贝与浅拷贝详解

    目录 Cloneable接口源码 浅拷贝案例 Pet类定义 Person类定义 浅拷贝问题-代码测试 深拷贝案例 Pet类重写clone()方法 Person的clone()方法中调用Pet的clone方法 浅拷贝问题解决-深拷贝代码测试 总结 Cloneable接口源码 Cloneable接口: 实现此接口的类——可被推断java.lang.Object的clone()方法可以被合法调用-以实现类实例:属性到属性的拷贝. 如果一个类未实现Cloneable接口,那么调用clone()方法时,会

  • Java的Comparable,Comparator和Cloneable三大接口详解

    目录 1.比较器 1.1Comparable接口 1.2Comparator接口 2.Cloneable接口 2.1深拷贝和浅拷贝 总结 1.比较器 ①比较器的引入 a.首先,当我们单一地比较某一种数据类型的数组时,可以直接用Arrays.sort()进行实现 b.而当我们同时含有多个参数时,并没有告诉我们按照什么来进行排序,此时,若是用Arrays.sort()就会出现报错的情况  基于这种情况,我们了解到,若是要将自定义类型进行大小比较 ,就要引入能够实现比较的接口,下面我们介绍Compar

  • Java并发教程之Callable和Future接口详解

    刚把Thread 的知识理了一遍. Runnable是一个接口,而Thread是Runnable的一个实现类. 所以也就有了之前创建线程的两种方法 继承Thread 实现Runnable 我们看一下新建线程的方法: 都是得传入一个Runnable对象(这句话很关键) 所以传入一个Runnble和Thread对象都行. 现在引入创建线程的第三种方法:Callable 为了实现 Runnable,需要实现不返回任何内容的 run()方法,而对于 Callable,需要实现在完成时返回结果的 call

  • java 中使用匿名类直接new接口详解及实例代码

    java:使用匿名类直接new接口 java中的匿名类有一个倍儿神奇的用法,见下面代码示例: package contract; public interface ISay { void sayHello(); } 上面是一个简单的接口,下面是如何使用: package jimmy; import contract.ISay; public class Program { public static void main(String[] args) { ISay say = new ISay()

  • Java中的多态、抽象类和接口详解

    目录 1.多态 1.1 向上转型 1.2 向下转型 1.3 实现多态的条件 1.4多态的特点与使用 1.5多态的应用 以父类类型作为方法的参数 使用父类型作为方法的返回值 1.6 多态的注意点 2.抽象类 2.1 abstract关键字 2.2 抽象方法和普通方法的区别 2.3 抽象类和普通类的区别 2.4 本质 2.5 抽象类局限 3.接口 3.1 定义接口 3.2 使用接口 3.3 实现多个接口 3.4 jdk8接口新特性 1.多态 一个特定类型的变量,可以引用多个不同类型的对象,并且能自动

  • Java集合之Comparable和Comparator接口详解

    目录 Comparable接口 Comparable接口简单应用 Comparator接口 Comparator接口简单应用 Comparator接口 VS Comparable接口 总结 java提供了Comparable接口与Compatator接口,它们为数组或集合中的元素提供了排序逻辑,实现此接口的对象数组或集合可以通过Arrays.sort或Collections.sort进行自动排序 Comparable接口 一个类实现了Comparable接口,则表明这个类对象之间是可以互相比较的

  • Java基础巩固抽象类与接口详解

    目录 1.抽象类 1.1.什么是抽象类 1.2.抽象类的用法 1.3.抽象类特点(限制条件) 2.接口 2.1.什么是接口 2.2.接口的用法 2.3.如何使用接口 2.4.接口的特点(限制条件) 2.5.如何实现多个接口 2.6.接口于接口之间的继承关系 2.7.如何使用接口 抽象类与接口 1.抽象类 1.1.什么是抽象类 如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类 1.2.抽象类的用法 一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract

  • Java零基础也看得懂的单例模式与final及抽象类和接口详解

    目录 1.单例模式 1.饿汉式和懒汉式的实现 2.饿汉式 3.懒汉式 4.懒汉式和饿汉式的区别 2.final的使用 1.基本介绍 2.使用场景 3.使用注意事项和细节讨论 3.抽象类 1.基本介绍 2.使用注意事项和细节讨论 4.接口 1.基本介绍 2.注意事项和细节讨论 3.实现接口与继承的区别 4.接口与继承同时出现如何访问属性 5.接口的多态特性 1.单例模式 1.饿汉式和懒汉式的实现 步骤: 将构造器私有化 类的内部创建对象 向外暴露一个静态的公共方法 2.饿汉式 class Scho

  • Java基础学习之接口详解

    目录 概述 定义格式 含有抽象方法 含有默认方法和静态方法 含有私有方法和私有静态方法 基本的实现 实现的概述 抽象方法的使用 默认方法的使用 静态方法的使用 私有方法的使用 接口的多实现 抽象方法 默认方法 静态方法 优先级的问题 接口的多继承 其他成员特点 概述 接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量.构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法 (JDK 9). 接

  • Java集合框架之List ArrayList LinkedList使用详解刨析

    目录 1. List 1.1 List 的常见方法 1.2 代码示例 2. ArrayList 2.1 介绍 2.2 ArrayList 的构造方法 2.3 ArrayList 底层数组的大小 3. LinkedList 3.1 介绍 3.2 LinkedList 的构造方法 4. 练习题 5. 扑克牌小游戏 1. List 1.1 List 的常见方法 方法 描述 boolean add(E e) 尾插 e void add(int index, E element) 将 e 插入到 inde

  • Java 从Set里面取出有序的记录详解及实例

    Java 从Set里面取出有序的记录详解及实例 Set里面的记录是无序的,如果想使用Set,然后又想里面的记录是有序的,就可以使用TreeSet,而不是HashSet,在使用TreeSet的时候,里面的元素必须是实现了Comparable接口的,TreeSet在进行排序的时候就是通过比较它们的Comparable接口的实现! 下面是HashSet的无序和TreeSet的有序的比较: Test类: import java.util.HashSet; import java.util.Iterato

随机推荐