目录
1. 理解接口的概念
2. 学会接口的语法(关键字implements)
3. 掌握接口的用法
4. 明白接口的特性
5. 教你如何实现多个接口
6. 接口之间是怎么继承的
7. 给接口举个例子
️7.1 Comparable接口
️7.2 比较器Comparator
8. Clonable接口和深拷贝
️8.1 Cloneable接口
️8.2 浅拷贝
️8.3 深拷贝
9. 接口和抽象类的区别
1. 理解接口的概念
接口就是公共的规范标准,如果要使用就要遵守这个标准, 而在Java中,接口可以看成是:一种特殊的类, 它的规范标准就是,里面全部都是由全局常量和公共的抽象方法组成, 并且它是解决java无法使用多继承的一种手段,所以如果要使用就要遵守这个标准
2. 学会接口的语法(关键字implements)
使用interface来修饰接口
注意:
(1)创建接口时,接口的命名一般以大写字母 I 开头
(2)建议接口中的方法和属性不要加任何修饰符号, 保持代码的简洁性
3. 掌握接口的用法
接口是不能直接使用的,必须要有一个类来实现该接口,实现接口中的所有抽象方法
格式就是这样
class 类名称 implements 接口名称{
//
}
4. 明白接口的特性
(1)接口当中的成员变量,默认都是 public static final 修饰的
(2)接口中的成员方法,默认都是抽象方法
也就是public abstract 修饰的
(3)接口中的普通成员方法,是不能有具体的实现的
这里就报错了
(4)接口中的普通成员方法,如果要有具体实现,就必须加上default【从JDK8开始】
(5) 接口中可以有静态的成员方法,
但是不管是静态方法还是default方法都是public修饰的
(6)接口本身也是不可以进行实例化的
(7) 类和接口的关系是使用 implements 来关联的
(8)一个接口可以引用,具体实现类的,向上转型
(9)接口中不能有静态代码块,实例代码块,构造方法
(10)一个抽象类实现一个接口,可以不重写这个抽象方法,但是这个类一旦被使用,就也要重写构造方法
5. 教你如何实现多个接口
java中是不支持多继承的,一个类只能有一个父类,那么如何实现多个类的使用
这就要用到接口了
一个类可以实现多个接口。
下面看例子
这个是个抽象类动物
abstract class Animal { public String name; public int age; public Animal(String name, int age) { this.name = name; this.age = age; } public abstract void eat() ;}
然后再看两个接口
interface IRunning { public void run() ;}interface IFlying { public void fly();}
下面创建一个动物 狗
⚜️如何使用接口呢,很简单,直接在子类继承父类的后面 加关键字 然后连接接口就可以了
class Dog extends Animal implements IRunning{ public Dog(String name, int age) { super(name, age); } @Override public void eat() { System.out.println(name + "正在吃狗粮! "); } @Override public void run(){ System.out.println(name+" 正在跑 "); }}
再创建一个动物 鸟
这里注意,在创建鸟时使用了两个接口 关键字implements后面 跟两个接口,中间用逗号连接
并且还要注意的是,一个类在实现多个接口的时候,每个接口中的抽象方法都要实现,否则类必须设置成抽象类
class Bird extends Animal implements IRunning,IFlying{ public Bird(String name, int age) { super(name, age); } @Override public void eat() { System.out.println(name + "正在吃鸟粮! "); } @Override public void run(){ System.out.println(name+" 正在慢跑走 "); } @Override public void fly(){ System.out.println(name+" 正在用翅膀飞 "); }}
上面的这个例子,说明了java中 ,
一个类继承一个父类,同时实现多种接口
而接口表达的作用是,具有___功能或特性
6. 接口之间是怎么继承的
类和类之间是单继承的,一个类可以有多个接口,接口和接口之间是可以多继承的。
也就是,用接口就可以实现多继承。
下面看代码,例子
interface IA { void funcA();}interface IB{ void funcB();}//扩展功能--接口的继承interface IC extends IA,IB{ void funC();}class T implements IC { @Override public void funcA() { } @Override public void funcB() { } @Override public void funC() { }}
这个例子中,为了实现接口的继承,
使用了extends关键字,在关键字后面跟两接口,中间用逗号连接
接口之间的继承相当于把多个接口合并在一起,也就是扩展功能
7. 给接口举个例子
️7.1 Comparable接口
比较自定义类型的大小接口Comparable
如果是自定义类型数据,需要比较大小,那就要先明确根据什么去比较大小,
这里也可以简化一下代码
@Override public int compareTo(Student o) { return this.age - o.age; }
这里的this就是student,o就是student1,这两个根据age比较大小
public static void main(String[] args) { Student student = new Student("zhang san",20,60); Student student1 = new Student("li si",21,70); Student student2 = new Student("wang wu",21,80); if(student.compareTo(student1) > 0){ System.out.println("student > student1"); }else if (student.compareTo(student1) == 0){ System.out.println("student == student1"); }else { System.out.println("student < student1"); } }
public static void main(String[] args) { Student[] students = new Student[3]; students[0] = new Student("zhang san",22,60); students[1] = new Student("li si",21,70); students[2] = new Student("wang wu",21,80); System.out.println("排序前" + Arrays.toString(students)); Arrays.sort(students); System.out.println("排序后" + Arrays.toString(students)); }
⚜️如果以后是自定义类型的数据,牵扯到大小比较,需要进行一些设计的。比如实现接口
️7.2 比较器Comparator
比较器Comparator
比较器Comparator比前面的Comparable更加灵活,
因为Comparable比较是写的固定的,而Comparator可以根据用户的需求去指定选择根据什么样的方式进行比较,
比如说比较年龄
class AgeComparator implements Comparator { @Override public int compare(Student o1, Student o2) { return o1.age - o2.age; }}
比如说比较分数
class AgeComparator implements Comparator { @Override public int compare(Student o1, Student o2) { return o1.age - o2.age; }}
需要比较什么就选择什么,非常的灵活
public static void main(String[] args) { Student student = new Student("zhang san",20,60); Student student1 = new Student("li si",21,70); AgeComparator ageComparator =new AgeComparator(); int ret = ageComparator.compare(student,student1); System.out.println(ret); ScoreComparator scoreComparator = new ScoreComparator(); int ret2 = scoreComparator.compare(student,student1); System.out.println("分数比较" + ret2); }
⚜️当然两个也是可以共存的
compareTo是根据学生对象去调用的,而Comparator是根据对应选择比较来调用的
⚜️前面比较的都是数字,那么Compartor是如何来比较字符串的
下面来进行name的比较
注意看name是String类型,String实现了Comparable接口
所以它默认有Comparable方法那就可以直接这样做了
class NameComparator implements Comparator { @Override public int compare(Student o1, Student o2) { return o1.name.compareTo(o2.name); }}
我们也可以自己写一个sort方法来实现排序过程,使用冒泡排序
public static void sort(Comparable[] array) { for (int i = 0; i i; j--) { if (array[j].compareTo(array[j+1]) > 0) { // 顺序不符合要求, 交换两个变量的位置 Comparable tmp = array[j - 1]; array[j - 1] = array[j]; array[j] = tmp; } } } }
8. Cloneable接口和深拷贝
️8.1 Cloneable接口
这是一个空接口(标记接口),没有抽象方法,也就是类可以被克隆
Cloeable表示person这个类可以被克隆
但是如果要克隆那就必须要重写clone这个方法
可以看到调用的是Object这个cloen方法
可以简单的看一下克隆过程
class person implements Cloneable{ public int age = 11; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "person{" + "age=" + age + '}'; }}public class Test01 { public static void main(String[] args) throws CloneNotSupportedException { person person = new person(); person person1 = (person) person.clone(); }}
所以,Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”.
但是要想合法调用 clone 方法, 必须要 先实现 Clonable 接口,
️8.2 浅拷贝
下面看这样的一段代码
class Money { public double money = 19.9;}class person implements Cloneable{ public int age = 10; public Money m = new Money(); @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "person{" + "age=" + age + '}'; }}public class Test01 { public static void main(String[] args) throws CloneNotSupportedException { person person = new person(); person person1 = (person) person.clone(); System.out.println(person.m.money); System.out.println(person1.m.money); }}
它会输出什么
如果此时修改
person1.m.money = 99;
那么输出会不会变化呢,要明白这个问题,就要先搞清楚这段代码的存储方式
都是指向同一个money的所以,修改一个,另一个也会变化,这样的存储方法就叫做浅拷贝
️8.3 深拷贝
但是最后指向的都是
所以修改一个另一个也会被改变,这个也就是浅拷贝
所以深拷贝就是希望,最后指向的不是一块空间,修改一个另一个不会被改变
深拷贝就是希望实现这样的一个效果,
下面修改一下试试看
person1.m.money = 99;
和我们希望的一样,修改后不影响另一个值
9. 接口和抽象类的区别
区别 | 抽象类 | 接口 |
---|---|---|
成员变量 | 普通类一样 | 默认被public static final修饰 |
成员方法 | 构造方法或普通方法 | 抽象方法,静态方法,default默认方法 |
子类使用 | 用extends关键字继承抽象类 | 用implements关键字实现接口 |
子类限制 | 一个子类继承一个抽象类 | 一个子类实现多个接口 |
关系 | 一个抽象类可以实现若干接口 | 接口不能继承抽象类,但接口可以使用 extends关键字继承多个父接口 |
权限 | 和普通类一样 | public |