类和对象进阶 - 接口
1. 接口
1.1 接口定义与重点
1. 使用 interface关键字定义接口
public interface 接口名称{ }
2. 接口中的方法不能有具体的实现
不能有具体的实现 是因为接口中的方法默认都是抽象方法
3. 如果要有具体实现 必须用default / static修饰
4. 在接口中定义的成员变量 默认都是用public static final修饰的常量
5. 接口中的抽象方法 默认都是用public abstract修饰的
7. 接口不能用来实例化对象
8. 类和接口之间的关系 可以使用implements来关联
9. 一个类 继承一个普通类/抽象类 还可以同时关联接口
10. 一个类实现接口后 必须重写接口中所有的抽象方法
11. 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
12. 接口和接口之间可以使用关键字extends。表示某个接口拓展了某个接口的功能。
interface A extends B,C,D {}
13. 子类继承抽象类或者关联接口后,可以用抽象类/接口引用 引用子类对象 发生向上转型
1.2 理解接口
代码:
https://github.com/znxcmakhsd/JavaSE-code/tree/main/11-23/demo2
1.3 抽象类和接口的区别
1. 抽象类中可以有普通的成员变量和方法 但是接口中的成员变量只能是public static final 接口中的成员方法只能是public abstract抽象方法
2. 一个类只能继承一个抽象类 但是一个类可以实现多个接口 所以接口解决了java中不能多继承的问题
2. 几个重要的接口
2.1 comparable接口
如何比较两个对象的大小 ?
用 > 比较运算符 ?
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 Main { public static void main(String[] args) { Student student1 = new Student("abc",18); Student student2 = new Student("abd",19); if (student1 > student2) { System.out.println("student1 > student2"); } } }
不能用>比较对象 因为比较运算符两边的操作数只能是 基本类型整数或浮点数
比如: 1 > 2 1.1 > 1.2
那么 用什么办法比较对象 ?
这个问题稍后回答 先来看如何比较两个字符串大小
package demo2; 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 Main { public static void main(String[] args) { Student student1 = new Student("abc",18); Student student2 = new Student("abd",19); String str1 = "abc"; String str2 = "abd"; if (str1.compareTo(str2) >= 0) { System.out.println("str1 >= str2"); }else { System.out.println("str1 < str2"); } } }
如图 str1 < str2 成功比较出了字符串的大小 但是 它是怎么比较的 原理是什么?
首先java中的字符串是对象 str1是"abc"这个字符串对象的引用 所以str1这个对象的引用可以访问String类中的方法
String类实现了Compareable这个接口 然后重写了Compareable接口中的compareTo方法 如下图
所以 比较字符串大小 实际上调用的是String类自己的compareTo方法进行比较的
我们也可以模仿这种方法 对我们自己的对象进行比较
package demo2; 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.name.compareTo(o.name); // 用年龄进行比较 return this.age - this.age; } } public class Main { public static void main(String[] args) { Student student1 = new Student("abc",20); Student student2 = new Student("abd",19); if (student1.compareTo(student2) >= 0) { System.out.println("student1 >= student2"); }else { System.out.println("student1 < student2"); } } }
用名字比较:
用年龄进行比较:
接下来 有个重要的问题是 为什么一定要实现compareable这个接口 ?
我们自己是可以写一个函数进行比较的 如下例
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 + '}'; } /*@Override public int compareTo(Student o) { // 用名字进行比较 //return this.name.compareTo(o.name); // 用年龄进行比较 return this.age - this.age; }*/ public int my_compareTo(Student o){ // 用名字进行比较 //return this.name.compareTo(o.name); // 用年龄进行比较 return this.age - this.age; } } public class Main { public static void main(String[] args) { Student student1 = new Student("abc",20); Student student2 = new Student("abd",19); if (student1.my_compareTo(student2) >= 0) { System.out.println("student1 >= student2"); }else { System.out.println("student1 < student2"); } } }
这个问题的回答通过下例说明
package demo2; import java.util.Arrays; 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.name.compareTo(o.name); // 用年龄进行比较 return this.age - o.age; }*/ public int my_compareTo(Student o){ // 用名字进行比较 //return this.name.compareTo(o.name); // 用年龄进行比较 return this.age - o.age; } } public class Main { public static void main(String[] args) { Student student1 = new Student("a",20); Student student2 = new Student("c",19); Student student3 = new Student("b",21); Student[] arr = {student1,student2,student3}; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } /*public static void main1(String[] args) { Student student1 = new Student("abc",20); Student student2 = new Student("abd",19); if (student1.my_compareTo(student2) >= 0) { System.out.println("student1 >= student2"); }else { System.out.println("student1 < student2"); } }*/ }
如图报错 报错的原因是什么?
package demo2; import java.util.Arrays; 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.name.compareTo(o.name); // 用年龄进行比较 return this.age - o.age; } public int my_compareTo(Student o){ // 用名字进行比较 //return this.name.compareTo(o.name); // 用年龄进行比较 return this.age - o.age; } } public class Main { public static void main(String[] args) { Student student1 = new Student("a",20); Student student2 = new Student("c",19); Student student3 = new Student("b",21); Student[] arr = {student1,student2,student3}; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } /*public static void main1(String[] args) { Student student1 = new Student("abc",20); Student student2 = new Student("abd",19); if (student1.my_compareTo(student2) >= 0) { System.out.println("student1 >= student2"); }else { System.out.println("student1 < student2"); } }*/ }
也可以自己实现排序
package demo2; import java.util.Arrays; 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.name.compareTo(o.name); // 用年龄进行比较 return this.age - o.age; } public int my_compareTo(Student o){ // 用名字进行比较 //return this.name.compareTo(o.name); // 用年龄进行比较 return this.age - o.age; } } public class Main { public static void my_sort(Comparable[] comparables) { for (int i = 0;i < comparables.length;i++) { for (int j = 0;j < comparables.length-i-1;j++) { if (comparables[j].compareTo(comparables[j+1]) > 0) { Comparable tmp = comparables[j]; comparables[j] = comparables[j+1]; comparables[j+1] = tmp; } } } } public static void main(String[] args) { Student student1 = new Student("a",20); Student student2 = new Student("c",19); Student student3 = new Student("b",21); Comparable[] arr = {student1,student2,student3}; /*Arrays.sort(arr);*/ my_sort(arr); System.out.println(Arrays.toString(arr)); } /*public static void main1(String[] args) { Student student1 = new Student("abc",20); Student student2 = new Student("abd",19); if (student1.my_compareTo(student2) >= 0) { System.out.println("student1 >= student2"); }else { System.out.println("student1 < student2"); } }*/ }
2.2 comparator 接口
comparable接口 有个不好的地方 如下图
comparator 接口可以很好解决这个问题 如下例
import java.util.Arrays; import java.util.Comparator; 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.name.compareTo(o.name); // 用年龄进行比较 return this.age - o.age; } } // 以年龄排序 class AgeComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.age - o2.age; } } // 以名字排序 class NameComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.name.compareTo(o2.name); } } public class Main { public static void main(String[] args) { Student student1 = new Student("a", 20); Student student2 = new Student("c", 19); Student student3 = new Student("b", 21); Student[] students = {student1, student2, student3}; // 比较器的使用 AgeComparator ageComparator = new AgeComparator(); NameComparator nameComparator = new NameComparator(); System.out.println(ageComparator.compare(student1, student2)); System.out.println(nameComparator.compare(student1, student2)); System.out.println("================================"); // 传入比较器排序 Arrays.sort(students,ageComparator); System.out.println(Arrays.toString(students)); System.out.println("================================"); Arrays.sort(students,nameComparator); System.out.println(Arrays.toString(students)); } }
2.3 Clonable接口和深浅拷贝
浅拷贝
问题引入:
报错的原因是什么 ? 如何实现拷贝 ?
报错原因有4个
class Person implements Cloneable { public String name; public Person(String name) { this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } public class Main { public static void main(String[] args) throws CloneNotSupportedException{ Person person1 = new Person("a"); Person person2 = (Person) person1.clone(); System.out.println(person2.name); } }
深拷贝
什么是深拷贝 ? 如何实现一个深拷贝 ?
package test; class Identity implements Cloneable { public int id = 1; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Person implements Cloneable { public String name; public Identity identity; public Person(String name) { this.name = name; this.identity = new Identity(); } @Override protected Object clone() throws CloneNotSupportedException { Person tmp = (Person) super.clone(); tmp.identity = (Identity) this.identity.clone(); return (Object) tmp; } } public class Main { public static void main(String[] args) throws CloneNotSupportedException{ Person person1 = new Person("a"); Person person2 = (Person) person1.clone(); System.out.println("修改之前: " + person1.identity.id); System.out.println("修改之前: " + person2.identity.id); System.out.println("============================="); person2.identity.id = 2; System.out.println("修改之后: " + person1.identity.id); System.out.println("修改之后: " + person2.identity.id); } public static void main1(String[] args) throws CloneNotSupportedException{ Person person1 = new Person("a"); Person person2 = (Person) person1.clone(); System.out.println(person2.name); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现