1.什么是接口
Java为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩容子类能力。
即:Java中使用抽象类/父类表示通用属性时,每个类只能继承一个类,假如子类已经从一个父类继承了,就不能再继续继承另外的父类。但每个类可以实现多个接口,这样子类就拥有了更多的能力。
微观概念:接口是一种能力和约定。
- 接口的定义:代表了某种能力
- 方法的定义:能力的具体要求
2.接口语法
API(应用程序编程接口): Application Program Interface
接口相当于特殊的抽象类,定义方式、组成部分与抽象类类似。
接口的定义语法:
接口的定义要求:
- 没有构造方法,不能创建对象
- 只能定义:公开静态常量、公开抽象方法
1 2 3 4 5
| public interface MyInterface { public static final String FIELD = "value"; public abstract void method(); }
|
1 2 3 4 5 6 7 8 9
| interface MyInterface { public static final String A = "hello"; String D = "good"; public abstract void method(); void m(); }
|
接口与抽象类的【相同】:
- 可编译为字节码文件(.class)
- 不能创建对象(接口不是类,也没有构造方法)
- 可以作为引用类型
- 具备Object类中所定义的方法
接口与抽象类的【不同】:
- 所有属性都只能且默认是公开静态常量,隐式使用public static final修饰
- 所有方法都只能且默认是公开抽象方法,隐式使用public abstract修饰
- 没有构造方法、没有动态/静态代码块
接口的使用语法:
1 2 3 4 5
| calss Sub extends Super implements 接口名,接口名 { @OverRide public 返回值 method() { ... } }
|
3.接口规范
- 任何类在实现接口时,必须实现接口中所有的抽象方法,否则此类为抽象类。
- 实现接口中抽象方法,访问修饰符必须是public。
4.接口引用
同父类一样,接口也可声明为引用,并指向真实类对象。
注意:
- 使用接口引用作为方法形参,实现更自然的多态(只关注能力-具备能力的类对象均可传入)
- 仅可调用接口中所声明的方法,不可调用实现类中独有的方法
- 可强转回真实类本身类型,进行独有方法调用(注意判断真实类对象 instanceof)
接口引用的应用(伪代码示例-eclipse可编译运行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
public class TestApply { public static void main(String[] args) { System.out.println("接口应用伪代码"); } } abstract class 船 implements 会漂浮的 { public abstract void 漂浮(); } class 小舟 extends 船 { public void 漂浮() {} } class 游艇 extends 船 { public void 漂浮() {} } class 木筏 extends 船 { public void 漂浮() {} } class 纸壳 {} class 纸壳箱 extends 纸壳 implements 会漂浮的 { public void 漂浮() { System.out.println("纸壳箱通过胶带多次山绕,具备了可以承载重量后,漂浮在水面上"); } } class 瓶子 {} class 矿泉水瓶 extends 瓶子 implements 会漂浮的 { public void 漂浮() { } } class 树 {} class 大木头 extends 树 implements 会漂浮的 { public void 漂浮() { } } class GameTeam {
public void 过汉江 (会漂浮的 n) { System.out.println("n可以传入具备 会漂浮的 能力的对象均可-多态"); } } interface 会漂浮的 { public abstract void 漂浮(); }
|
接口引用指向实现类对象,以及强转回实现类对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
interface Runnable { public abstract void run(); }
interface Swimmable { public abstract void swim(); }
interface Climbable { void climb(); }
interface Flyable { void fly(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| public class TestApplyInterface { public static void main(String[] args) { Animal a = new Dog(); Runnable r = new Dog(); r.run(); r = new Cat(); r.run(); r = new Bus(); r.run(); if (r instanceof Bus) { Bus b = (Bus)r; System.out.println(b.seatNum); } } } class Animal{ String breed; int age; String sex; public void eat() {} public void sleep() {} }
class Dog extends Animal implements Runnable,Swimmable { String furColor; public void run() { System.out.println("狗在奔跑..."); } @Override public void swim() { System.out.println("狗在游泳..."); } }
class Cat extends Animal implements Runnable,Climbable{ String furColor; public void run() { System.out.println("猫在奔跑..."); } public void climb() { System.out.println("猫在爬树..."); } } class Fish extends Animal{ } class Bird extends Animal{ } class Bus implements Runnable{ int seatNum = 50; @Override public void run() { System.out.println("公交车在跑..."); } }
|
输出:
狗在奔跑…
猫在奔跑…
公交车在跑…
50
5.接口多继承
类与类:单继承,extends 父类名称
类与接口:多实现,implements 接口名1,接口名2,接口名3
接口与接口:多继承,extends 父接口1,父接口2,父接口3
接口继承多个父接口后,所有父接口的公开抽象方法也会被继承,进而在实现类中必须都要重写以覆盖抽象方法。
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| public class TestMultiExtends { public static void main(String[] args) { IC ic = new ClassE();
((IA)ic).ma(); ((IB)ic).mb(); ic.mc(); ((ID)ic).md(); System.out.println(ic instanceof IA); System.out.println(ic instanceof IB); System.out.println(ic instanceof IC); System.out.println(ic instanceof ID); System.out.println(ic instanceof ClassE); } } interface IA { void ma(); } interface IB extends IA { void mb(); } interface IC { void mc(); } interface ID extends IB, IC { void md(); }
class ClassE implements ID { public ClassE () {} @Override public void ma() { System.out.println("ma()"); } @Override public void mb() { System.out.println("mb()"); } @Override public void mc() { System.out.println("mc()"); } @Override public void md() { System.out.println("md()"); } }
|
6.接口使用
微观概念:接口是一种能力和约定。
- 接口的定义:代表了某种能力
- 方法的定义:能力的具体要求
宏观概念:接口是一种标准。
耦合度:模块与模块之间的关联程度,关联的越密切,耦合越高;越松散,耦合越低。
思路顺序:
(1)接口/标准
(2)接口使用者
(3)接口实现者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| public class TestUsbInterface { public static void main(String[] args) { Computer computer = new Computer(); Fan myFan = new Fan(); computer.on(myFan); computer.executeUSB(); Lamp myLamp = new Lamp(); computer.on(myLamp); computer.executeUSB(); USBDisk myDisk = new USBDisk(); computer.on(myDisk); computer.executeUSB(); } }
interface USB { public abstract void service(); }
class Computer { USB usb1; public void on(USB usb) { this.usb1 = usb; } public void executeUSB() { usb1.service(); } }
class Fan implements USB { @Override public void service() { System.out.println("通电---旋转"); } } class Lamp implements USB { @Override public void service() { System.out.println("通电---照明"); } } class USBDisk implements USB { @Override public void service() { System.out.println("通电---读写"); } }
|
7.接口回调
先有接口的使用者,后有接口的实现者。
案例:对一组学生对象进行排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
public interface Comparable<T> {
public int compareTo(T stu); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
public class Tool {
public static void sort(Student[] stus) { for (int i = 0; i < stus.length - 1; i++) { for (int j = 0; j < stus.length-1-i; j++) { if (stus[j] instanceof Comparable) { Comparable currentStu = (Comparable)stus[j]; if (currentStu.compareTo(stus[j+1]) > 0) { Student tmp = stus[j]; stus[j] = stus[j+1]; stus[j+1] = tmp; } } } } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
public class TestCallback { public static void main(String[] args) { Student[] students = new Student[] { new Student("tom", 20, "male", 99.0), new Student("jack", 21, "male", 98.0), new Student("annie", 19, "female", 100.0), new Student("marry", 25, "female", 88.0), new Student("john", 18, "male", 76.0), }; Tool.sort(students); for (Student student : students) { System.out.println(student.name + " " + student.score); } } }
class Student implements Comparable<Student> { String name; int age; String sex; double score; public Student() { } public Student(String name, int age, String sex, double score) { this.name = name; this.age = age; this.sex = sex; this.score = score; } @Override public int compareTo(Student stu) { if (this.score > stu.score) { return 1; } else if (this.score < stu.score) { return -1; } return 0; } }
|
接口回调的理解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public class TestTeacherSort { public static void main(String[] args) { Teacher[] ts = new Teacher[] { new Teacher("eric", 30), new Teacher("abby", 29), new Teacher("john", 22), new Teacher("sani", 33), }; java.util.Arrays.sort(ts); } } class Teacher implements Comparable<Teacher> { String name; int age; public Teacher(String name, int age) { super(); this.name = name; this.age = age; } @Override public int compareTo(Teacher o) { if (this.age > o.age) { return 1; } else if (this.age < o.age) { return -1; } return 0; } }
|
验证哥德巴赫猜想
输入一个大于6的偶数,输出这个偶数能够分解为哪两个质数的和。
使用Java接口interface的方式实现思路:
① 先有接口/标准 - 约定
② 程序员B - 先有接口使用者,以工具方法传参形式编写逻辑(接口回调) : void checkGoldBach()
③ 程序员A - 后有接口实现者,根据接口规范编写实现类逻辑(方法覆盖) : class ProgramerPrime implements MathTool {}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| import java.util.Scanner;
public class TestGoldBach { public static void main(String[] args) { int num = 0; num = getInputNum(); checkGoldBach(num, new ProgramerPrime());
}
public static void checkGoldBach (int n, MathTool tool) { for (int i = 0; i <= n/2; i++) { if (tool.getPrimeNum(i) && tool.getPrimeNum(n-i)) { if (n == i + (n-i)) { System.out.println("验证结果:" + i + " " + (n-i)); } } else { continue; } } } public static int getInputNum () { Scanner input = new Scanner(System.in); int evenNum = 0; while (true) { System.out.print("请输入1个大于6的偶数:"); evenNum = input.nextInt(); if (evenNum > 6 && evenNum%2 == 0) { System.out.println("开始验证哥德巴赫猜想..."); break; } else { System.out.println("输入不正确,请重新输入!"); } } input.close(); return evenNum; } }
interface MathTool { boolean getPrimeNum (int n); }
class ProgramerPrime implements MathTool {
@Override public boolean getPrimeNum(int n) { for (int i = 2; i < n; i++) { if (n % i == 0) { return false; } }
return true; } }
|
输出:
请输入1个大于6的偶数:20
开始验证哥德巴赫猜想…
验证结果:1 19
验证结果:3 17
验证结果:7 13