首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
第一章:OOP:继承
第二章:关键字 super
第三章:关键字 static
第四章:成员变量初始化
第五章:OOP:多态
第六章:关键字 native
第七章:关键字 final
第八章:Object 类的使用
第九章:抽象类
第十章:接口
第十一章:经典接口介绍
第十二章:包装类
第十三章:内部类
当前位置:
首页>>
技术小册>>
Java语言基础6-面向对象高级
小册名称:Java语言基础6-面向对象高级
11.1 经典接口的介绍 11.1.1 java.lang.Comparable - 基本数据类型的数据(除了 boolean 类型以外)比较大小的话,直接使用比较运算符即可;但是,引用数据类型是不能直接使用比较运算符来比较大小的,那么,怎么办呢? - Java 给所有的引用数据类型的大小比较,提供了一个标准接口,就是 java.lang.Comparable 接口。 ```bash package java.lang; import java.util.*; public interface Comparable<T> { public int compareTo(T o); } ``` - 那么,如果我们想是的我们某个类的对象可以比较大小,怎么做? - ① 那个类的对象要比较大小,那个类就需要实现 java.lang.Comparable 接口,并重写方法。 - 方法体就是如何比较当前对象和指定的另一个对象大小的规则。 - ② 对象比较大小的时候,通过对象调用 compareTo 方法,根据方法的返回值决定谁大谁小。 - this 对象(调用 compareTo 方法的对象)大于指定对象(传入 compareTo() 的参数对象),返回正整数。 - this 对象(调用 compareTo 方法的对象)小于指定对象(传入 compareTo() 的参数对象),返回负整数。 - this 对象(调用 compareTo 方法的对象)等于指定对象(传入 compareTo() 的参数对象),返回零。 温馨提示:这种方式称为自然排序或内部比较器排序。 - 自然排序:Comparable 接口强行对实现它的每个类的对象进行整体排序,类的 compareTo 方法被称为它的自然比较方法。 - 内部比较器排序:在比较对象所在类的内部完成比较规则的制定。 - 示例: ```bash package com.github.demo11; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Student implements Comparable<Student> { private String name; private int age; private double score; public Student() {} public Student(String name, int age, double score) { this.name = name; this.age = age; this.score = score; } public Student(String name, int age) { this.name = name; this.age = age; } @Override public int compareTo(Student o) { return Integer.compare(this.age, o.age); } @Override public String toString() { return "Student{" + "name='" + this.name + '\'' + ", age=" + this.age + ", score=" + this.score + '}'; } } ``` ```bash package com.github.demo11; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Test { public static void main(String[] args) { Student student = new Student("张三", 35, 99); Student student2 = new Student("李四", 25, 88); /* * 按照年龄进行比较 * * 如果是0,表示两数相等。 * 如果是正数,那么第一个数大于第二个数。 * 如果是负数,那么第一个数小于第二个数。 */ int sort = student.compareTo(student2); if (sort > 0) { System.out.println("student比student2大"); } else if (sort == 0) { System.out.println("student和student2一样大"); } else { System.out.println("student比student2小"); } } } ``` 示例:冒泡排序 ```bash package com.github.demo12; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Person implements Comparable<Person> { private String name; private int age; public Person() {} public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + this.name + '\'' + ", age=" + this.age + '}'; } @Override public int compareTo(Person o) { return Integer.compare(this.age, o.age); } } ``` ```bash package com.github.demo12; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Test { public static void main(String[] args) { Person p1 = new Person("张三", 25); Person p2 = new Person("李四", 74); Person p3 = new Person("王五", 10); Person p4 = new Person("赵六", 34); Person p5 = new Person("天气", 59); Person[] persons = new Person[] {p1, p2, p3, p4, p5}; System.out.println("---------------排序前:---------------"); printArray(persons); System.out.println("---------------排序后:---------------"); for (int i = 0; i < persons.length -1; i++) { for (int j = 0; j < persons.length - i - 1; j++) { if (persons[j].compareTo(persons[j + 1]) > 0) { Person temp = persons[j]; persons[j] = persons[j + 1]; persons[j + 1] = temp; } } } printArray(persons); } private static void printArray(Person[] persons) { for (Person person : persons) { System.out.println(person); } } } ``` 示例:自定义数组工具排序类 ```bash package com.github.demo13; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Arrays { public static void sort(Object[] arr) { for (int i = 0; i < arr.length - 1; i++) { for (int j = 0; j < arr.length - i - 1; j++) { // 如果arr数组中的元素实现了Comparable接口,就进行排序 // 否则,原样输出 if (arr[j] instanceof Comparable) { Comparable comparable = (Comparable)arr[j]; if (comparable.compareTo(arr[j + 1]) > 0) { Object temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } else { break; } } } } } ``` ```bash package com.github.demo13; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Person implements Comparable<Person> { private String name; private int age; public Person() {} public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + this.name + '\'' + ", age=" + this.age + '}'; } @Override public int compareTo(Person o) { return Integer.compare(this.age, o.age); } } ``` ```bash package com.github.demo13; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Test { public static void main(String[] args) { Person p1 = new Person("张三", 25); Person p2 = new Person("李四", 74); Person p3 = new Person("王五", 10); Person p4 = new Person("赵六", 34); Person p5 = new Person("天气", 59); Person[] persons = new Person[] {p1, p2, p3, p4, p5}; System.out.println("---------------排序前:---------------"); printArray(persons); System.out.println("---------------排序后:---------------"); Arrays.sort(persons); printArray(persons); } private static void printArray(Person[] persons) { for (Person person : persons) { System.out.println(person); } } } ``` 11.1.2 java.util.Comparator - 思考如下场景: - ① 如果一个类,没有实现 java.lang.Comparable 接口,而这个类不方便修改(比如:我们拿到的是第三方类,只有 .class 文件,没有源文件),那么这样的对象要进行比较大小该怎么办? - ② 如果一个类,实现了 java.lang.Comparable 接口,也指定了两个对象比较大小的规则,但是此时我不想按照它预定义的规则进行对象大小的比较,但是我又不能去修改这个类,因为会影响到其他地方的使用,那么这样的对象要进行比较大小该怎么办? - Java 在设计类库之初,已经考虑到这种情况了,所以又增加了一个 java.util.Comparator 接口。 package java.util; @FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); } - 那么,我们想要比较某个类的两个对象的大小,该怎么办? - ① 编写一个类,称为比较器类型,实现 java.util.Comparator 接口,并重写方法。 - 方法体就是如何比较当前对象和指定的另一个对象大小的规则。 - ② 比较大小的时候,通过比较器类型的对象调用 compare() 方法,将要比较大小的两个对象作为 compare 方法的实参传入,根据方法的返回值决定谁大谁小。 - o1 对象大于 o2 ,返回正整数。 - o1 对象小于 o2 ,返回负整数。 - o1 对象等于 o2 ,返回零。 温馨提示:这种方式称为自定义排序或外部比较器排序。 - 示例: ```bash package com.github.demo14; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Person { private String name; private int age; private double salary; public Person() {} public Person(String name, int age, double salary) { this.name = name; this.age = age; this.salary = salary; } @Override public String toString() { return "Person{" + "name='" + this.name + '\'' + ", age=" + this.age + ", salary=" + this.salary + '}'; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } public double getSalary() { return this.salary; } public void setSalary(double salary) { this.salary = salary; } } ``` ```bash package com.github.demo14; import java.util.Comparator; /** * @author maxiaoke.com * @version 1.0 * @return */ public class PersonAgeCompare implements Comparator<Person> { @Override public int compare(Person o1, Person o2) { return Integer.compare(o1.getAge(), o11.getAge()); } } ``` ```bash package com.github.demo14; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Test { public static void main(String[] args) { Person p1 = new Person("张三", 56, 5000); Person p2 = new Person("李四", 20, 9000); PersonAgeCompare compare = new PersonAgeCompare(); int sort = compare.compare(p1, p2); if (sort > 0) { System.out.println(p1.getName() + "的年龄比" + p11.getName() + "大"); } else if (sort < 0) { System.out.println(p1.getName() + "的年龄比" + p11.getName() + "小"); } else { System.out.println(p1.getName() + "的年龄和" + p11.getName() + "相等"); } } } ``` 示例:冒泡排序 ```bash package com.github.demo15; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Person { private String name; private int age; private double salary; public Person() {} public Person(String name, int age, double salary) { this.name = name; this.age = age; this.salary = salary; } @Override public String toString() { return "Person{" + "name='" + this.name + '\'' + ", age=" + this.age + ", salary=" + this.salary + '}'; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } public double getSalary() { return this.salary; } public void setSalary(double salary) { this.salary = salary; } } ``` ```bash package com.github.demo15; import java.util.Comparator; /** * @author maxiaoke.com * @version 1.0 * @return */ public class PersonAgeCompare implements Comparator<Person> { @Override public int compare(Person o1, Person o2) { return Integer.compare(o1.getAge(), o11.getAge()); } } ``` ```bash package com.github.demo15; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Test { public static void main(String[] args) { Person p1 = new Person("张三", 78, 100); Person p2 = new Person("李四", 16, 9000); Person p3 = new Person("王五", 39, 500); Person p4 = new Person("赵六", 20, 3000); Person[] persons = new Person[] {p1, p2, p3, p4}; System.out.println("----------------排序前----------------"); printArray(persons); System.out.println("----------------排序后----------------"); PersonAgeCompare compare = new PersonAgeCompare(); for (int i = 0; i < persons.length - 1; i++) { for (int j = 0; j < persons.length - i - 1; j++) { if (compare.compare(persons[j], persons[j + 1]) > 0) { Person temp = persons[j]; persons[j] = persons[j + 1]; persons[j + 1] = temp; } } } printArray(persons); } private static void printArray(Person[] persons) { for (Person person : persons) { System.out.println(person); } } } ``` 示例:自定义数组工具排序类 ```bash package com.github.demo16; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Person { private String name; private int age; private double salary; public Person() {} public Person(String name, int age, double salary) { this.name = name; this.age = age; this.salary = salary; } @Override public String toString() { return "Person{" + "name='" + this.name + '\'' + ", age=" + this.age + ", salary=" + this.salary + '}'; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } public double getSalary() { return this.salary; } public void setSalary(double salary) { this.salary = salary; } } ``` ```bash package com.github.demo16; import java.util.Comparator; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Arrays { public static void sort(Object[] arr, Comparator comparator) { for (int i = 0; i < arr.length - 1; i++) { for (int j = 0; j < arr.length - i - 1; j++) { if (comparator.compare(arr[j], arr[j + 1]) > 0) { Object temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } } ``` ```bash package com.github.demo16; import com.github.demo15.Person; import com.github.demo15.PersonAgeCompare; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Test { public static void main(String[] args) { Person p1 = new Person("张三", 78, 100); Person p2 = new Person("李四", 16, 9000); Person p3 = new Person("王五", 39, 500); Person p4 = new Person("赵六", 20, 3000); Person[] persons = new Person[] {p1, p2, p3, p4}; System.out.println("----------------排序前----------------"); printArray(persons); System.out.println("----------------排序后----------------"); PersonAgeCompare compare = new PersonAgeCompare(); Arrays.sort(persons, compare); printArray(persons); } private static void printArray(com.github.demo15.Person[] persons) { for (Person person : persons) { System.out.println(person); } } } ``` 11.1.3 java.lang.Cloneable - 在 Object 类中,有如下的方法: ```bash protected native Object clone() throws CloneNotSupportedException; ``` - 所有的类都可以重写这个方法,它是获取一个对象的克隆体对象,就是造一个和当前对象属性一模一样的对象,地址是不同的。 - 要求,重写这个方法的类需要实现 java.lang.Cloneable 接口,否则会报 CloneNotSupportedException 的异常。 - 示例: ```bash package com.github.demo17; import java.util.Objects; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Teacher implements Cloneable { private int id; private String name; public Teacher() {} public Teacher(int id, String name) { this.id = id; this.name = name; } public int getId() { return this.id; } public void setId(int id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || this.getClass() != o.getClass()) { return false; } Teacher teacher = (Teacher)o; return this.id == teacher.id && Objects.equals(this.name, teacher.name); } @Override public int hashCode() { return Objects.hash(this.id, this.name); } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Teacher{" + "id=" + this.id + ", name='" + this.name + '\'' + '}'; } } ``` ```bash package com.github.demo17; /** * @author maxiaoke.com * @version 1.0 * @return */ public class Test { public static void main(String[] args) throws CloneNotSupportedException { Teacher teacher = new Teacher(1, "张三"); Object clone = teacher.clone(); System.out.println(teacher == clone); // false System.out.println(teacher.equals(clone)); // true } } ``` 11.1.4 java.lang.Iterable - 在 JDK 1.5 之后引入了 java.lang.Iterable 接口。实现这个接口将允许对象成为 forEach 语句的目标。java.lang.Iterable 接口的定义如下所示: ```bash package java.lang; import java.util.Iterator; import java.util.Objects; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; /** * @since 1.5 */ public interface Iterable<T> { /** * 该方法是抽象方法,需要子类实现。 */ Iterator<T> iterator(); /** * @since 1.8 */ default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } /** * @since 1.8 */ default Spliterator<T> spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); } } ``` 注意:Java 中的数组或部分集合对象已经实现了 java.lang.Iterable 接口,那么就不需要程序员手动实现该抽象方法了;换言之,数组或部分集合对象可以使用 forEach 语法。 - forEach 语法: ```bash for(元素类型 元素名 : 数组名|集合对象){ } ``` 示例: ```bash package com.github.day08.foreach; import java.util.ArrayList; import java.util.List; /** * @author maxiaoke.com * @version 1.0 * @since 2023-01-16 14:53:09 */ public class TestForEach { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("张三"); list.add("李四"); list.add("王五"); for (String s : list) { System.out.println("s = " + s); } System.out.println("--------------"); int[] arr = {1, 2, 3}; for (int i : arr) { System.out.println("i = " + i); } } } ```
上一篇:
第十章:接口
下一篇:
第十二章:包装类
该分类下的相关小册推荐:
Java语言基础8-Java多线程
Mybatis合辑5-注解、扩展、SQL构建
Java必知必会-Maven初级
SpringBoot零基础到实战
深入理解Java虚拟机
Java并发编程
Java语言基础9-常用API和常见算法
Java语言基础2-运算符
经典设计模式Java版
Mybatis合辑3-Mybatis动态SQL
Java语言基础5-面向对象初级
Java语言基础11-Java中的泛型