4. 接口
4.1 什么是接口
-
引例:
添加游泳方法
- 不能添加到动物类(父类),因为兔子不会游泳
- 子类两个若不同人写,可能会有不同的方法名,不利于后续的调用

为解决上述问题,使用接口
-
接口: 接口是一个规则,且独立于继承体系之外
类比父类可以将接口理解为干爹
-
格式: 关键字
interface来定义public interface 接口名{...} -
使用: 接口和类之间的是实现关系,通过
implements关键字表示eg:
public class 类名 implements 接口 {...} -
注意:
- 接口不能实例化(不能创建变量)
- 接口的子类(实现类),要么重写接口中的所有抽象方法,要么实现类是一个抽象类
- 一个类可以实现多个接口,也可在继承一个类的同时,实现多个接口
public class 类名 implements 接口1, 接口2{...}
public class 类名 extents 父类 implements 接口1,接口2{...}
tips:爹只能有一个,但干爹可以有很多个
-
小练习

java
package oopinterface.text1;
public abstract class Animal {
//属性
String name;
String color;
//构造方法
public Animal() {
}
public Animal(String name, String color) {
this.name = name;
this.color = color;
}
//get/set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
//行为
public abstract void eat();
}
java
package oopinterface.text1;
public interface Swim {
public abstract void swim();
}
java
package oopinterface.text1;
public class Rabbit extends Animal{
//构造方法
public Rabbit() {
}
public Rabbit(String name, String color) {
super(name, color);
}
@Override
public void eat() {
System.out.println("兔子在吃胡萝卜");
}
}
java
package oopinterface.text1;
public class Frog extends Animal implements Swim{
public Frog() {
}
public Frog(String name, String color) {
super(name, color);
}
@Override
public void eat() {
System.out.println("青蛙在吃虫子");
}
@Override
public void swim() {
System.out.println("蛙泳");
}
}
java
package oopinterface.text1;
public class Dog extends Animal implements Swim{
public Dog() {
}
public Dog(String name, String color) {
super(name, color);
}
@Override
public void eat() {
System.out.println("狗在吃骨头");
}
@Override
public void swim() {
System.out.println("狗刨");
}
}
java
package oopinterface.text1;
public class Text {
static void main() {
Rabbit rabbit = new Rabbit("小白", "白色");
rabbit.eat();
Dog dog = new Dog("小黑", "黑色");
dog.eat();
dog.swim();
Frog frog = new Frog("小绿", "绿色");
frog.eat();
frog.swim();
}
}
4.2 接口成员的特点
- 成员变量: 只能是常量, 默认修饰符:
public static final - 构造方法: 没有
- 成员方法: 只能是抽象方法,默认修饰符:
public absturact
JDK7以前:接口中只能定义抽象方法
JDK8新特性:接口中可以定义有方法体的方法(初学暂时忽略)
JDK9新特性:接口中可以定义私有方法(初学暂时忽略)
验证:
java
package oopinterface.text2;
public interface Inter {
//成员变量只能是常量,有默认修饰符:public static final
//关键字是灰色,表示可写可不写
public static final int A = 10;
//没有构造方法,因为都不能创建对象
//成员方法只能是抽象方法,有默认修饰符:public abstract(JDK7及以前)
void method();
}
java
package oopinterface.text2;
import java.awt.*;
public class Text {
static void main() {
System.out.println(Inter.A);
//可以输出 10 }
}
反编译Inter.class

由此可见,编译时会自动补上
4.3 接口和类之间的关系
| x与x | 类型 | 解释 |
|---|---|---|
| 类与类 | 继承关系 | 只能单继承,不能多继承,但是可以多层继承 |
| 类与接口 | 实现关系 | 可以单实现,也可多实现,还可在继承一个类时同时实现多个接口 |
| 接口与接口 | 继承关系 | 可以单继承,也可多继承 |
注意:
- 如果多个接口中出现了重复的抽象方法,此时重写一次即可
- 接口继承接口用extents,继承多个用
,隔开
4.4 接口和抽象类的综合案例

思路1:

思路2:

java
package oopinterface.text3;
public class Person {
String name;
int age;
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
java
package oopinterface.text3;
public class Sporter extends Person{
public Sporter() {
}
public Sporter(int age, String name) {
super(age, name);
}
public void study(){
System.out.println("学习");
}
}
java
package oopinterface.text3;
public class Coach extends Person{
public Coach() {
}
public Coach(int age, String name) {
super(age, name);
}
public void teach(){
System.out.println("教");
}
}
java
package oopinterface.text3;
public interface English {
public void speakEnglish();
}
java
package oopinterface.text3;
public class PingPangPlayer extends Sporter implements English {
public PingPangPlayer() {
}
public PingPangPlayer(int age, String name) {
super(age, name);
}
@Override
public void speakEnglish() {
System.out.println("乒乓球队员在说英语");
}
@Override
public void study() {
System.out.println("乒乓球队员在学习");
}
}
java
package oopinterface.text3;
public class PingPangCoach extends Coach implements English{
public PingPangCoach() {
}
public PingPangCoach(int age, String name) {
super(age, name);
}
@Override
public void speakEnglish() {
System.out.println("乒乓球教练在说英语");
}
@Override
public void teach() {
System.out.println("乒乓球教练在教球");
}
}
java
package oopinterface.text3;
public class BasktablePlayer extends Sporter{
public BasktablePlayer() {
}
public BasktablePlayer(int age, String name) {
super(age, name);
}
@Override
public void study() {
System.out.println("学打篮球");
}
}
java
package oopinterface.text3;
public class BasktableCoach extends Coach{
public BasktableCoach() {
}
public BasktableCoach(int age, String name) {
super(age, name);
}
@Override
public void teach() {
System.out.println("篮球教练在教球");
}
}
java
package oopinterface.text3;
public class Text {
static void main() {
PingPangPlayer ppp = new PingPangPlayer(20, "ppp");
ppp.study();
ppp.speakEnglish();
PingPangCoach ppc = new PingPangCoach(30, "ppc");
ppc.teach();
ppc.speakEnglish();
BasktablePlayer bp = new BasktablePlayer(40, "bp");
bp.study();
BasktableCoach bc = new BasktableCoach(50, "bc");
bc.teach();
}
}
4.5 接口在JDK8和9中的新特性
-
JDK7及以前
接口中只能定义抽象方法
-
JDK8新特性
为了接口升级时向下兼容,接口中可以定义有方法体的方法(默认、静态)
- 默认方法
-
允许接口中定义默认方法,需使用关键字default修饰
作用:为了接口升级时,代码不报错
-
接口中默认方法的定义格式
- 格式:
public default 返回值类型 方法名(参数列表){} - 范例:
public default void show(){}
- 格式:
-
接口中默认方法的注意事项
- 默认方法不是抽象方法, 所以不能被强制重写。但若被重写,重写的时候去掉default关键字
- public可以省略, default不能省略
- 如果实现了多个接口,多个接口中存在相同名字的默认方法, 子类就必须对该方法进行重写
-
- 静态方法
-
允许接口中定义静态方法,需使用关键字static修饰
-
接口中静态方法的定义格式
- 格式:
public static 返回值类型 方法名(参数列表){} - 范例:
public static void show(){}
- 格式:
-
接口中静态方法的注意事项:
- 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
- public可以省,static不能省
-
- 默认方法
-
JDK9新特性
为了抽取重复代码,接口中可以定义私有方法(私有普通方法,私有静态方法)
- 意义:抽取接口中默认方法、静态方法的重复代码
- 格式1:
private 返回值类型 方法名(参数列表){}(默认方法用) - 格式2:
private static 返回值类型(参数列表){}(静态方法用)