6.1 接口
使用关键字
interface
来定义一个接口,接口的定义和类十分相似,分为接口声明和接口体
interface Runnable{
void run();
}
接口声明
定义一个接口包含接口声明和接口体,和类不同的是,定义接口需要使用interface
关键字来声明自己是一个接口。
interface 接口名字{
}
接口体
接口体包含常量声明(接口没有变量) 和抽象方法两部分。接口体中
只有抽象方法
,没有普通方法
。
接口体中所有常量访问权限一定都是public
,并且是static
常量,所有抽象方法访问权限一定都是public
允许省略public abstract
修饰符
总结下
- 接口没有变量,只有常量
public static final
- 接口只有抽象方法,没有普通方法
public abstract
- 前缀可以省略
public interface Runnable {
public static final String tag = "default";
public abstract void run();
}
省略后
public interface Runnable {
String tag = "default";
void run();
}
6.2 实现接口
Java语言中,接口由类来实现以便使用接口中的方法,一个类需要在类声明中使用关键字
implements
声明该类实现一个或者多个接口(如果多个接口,接口之间用,
分隔开)
class Cat extends Animal implements Eatable,Sleepable{
}
猫继承自动物,实现了,吃和睡这两个接口。
重写接口中的方法
如果一个类实现了某个接口,那么这个类必须重写这个接口中的
所有方法
这里有个小细节,我们知道接口中的方法是 public abstract
方法,那么在我们重写时需要注意以下两点
- 去掉
abstract
- 添加方法体,且方法一定是 public 访问权限,否则就降低了 访问权限,这样是不允许的
用户也可以自定义接口,一个Java源文件由**类**
和**接口**
组成。
interface Eatable {
String tag = "animal";
void eat();
}
class Cat implements Eatable {
public void eat() {
// 直接访问接口中的常量
System.out.println(tag);
System.out.println("小猫会吃");
}
}
class Test {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat();
}
}
animal
小猫会吃
如果一个类实现了一个接口,但是没有重写接口中的所有方法,那么这个类必须是**抽象类**
抽象类既可以重写接口中的方法,也可直接拥有接口中的方法
interface Eatable {
String tag = "animal";
void eat();
}
abstract class Cats implements Eatable {
}
接口的细节说明
程序可以用接口名访问接口中的常量,但是如果一个类实现了接口,那么该类可以在类体中直接使用该接口中的常量。
interface Eatable {
String tag = "animal";
void eat();
}
class Cat implements Eatable {
@Override
public void eat() {
// 通过接口名访问常量
System.out.println(Runnable.tag);
// 类内直接访问
System.out.println(tag);
}
}
- 如果 interface 前面加了 public 关键字,就这样的接口是一个
public 接口
,可以被任意一个类实现 - 不加 public 的接口是一个友好的接口,只能被同一个包内中的类实现
- 如果父类实现了某个接口,子类自然也就实现了该接口,不必显式地使用关键字 implements 实现这个接口
- 接口可以被继承,通过关键字 extends 继承另一个接口 (很少这样做)
6.3 接口的UML图
- 顶部是名字,接口名字必须是
斜体字
需要使用<<interface>>
修饰名字 - 第二层是常量层,格式 常量名:类型
- 第三层是方法层,格式 方法名(参数列表):返回值
6.4 接口回调
把实现某一类接口的类创建的对象的引用传递给该接口声明的变量,然后调用实现类的方法,这个过程称之为
接口的回调
这里和前面的上转型对象十分相似,但是叫法不同
interface Eatable {
String tag = "animal";
void eat();
}
class Cat implements Eatable {
@Override
public void eat() {
System.out.println("猫食肉");
}
}
class Rabbit implements Eatable{
@Override
public void eat() {
System.out.println("兔子食草");
}
}
class Test{
public static void main(String[] args) {
Eatable cat = new Cat();
cat.eat(); // 接口的回调
}
}
6.5 理解接口
接口的语法规则很容易记住,但是真正的理解接口更重要。
理解接口的关键
- 接口可以抽象出重要的行为标准,该行为标准用抽象方法表示。
- 可以把接口实现类的对象引用赋值为接口变量
6.6 接口与多态
上面我们知道了接口回调的概念,通过接口回调我们就可以实现多态。
不同的类,实现了同一接口,就具备了不同的实现方式,那么在接口回调方法时,就具备了多种形态。
interface Eatable {
String tag = "animal";
void eat();
}
class Cat implements Eatable{
@Override
public void eat() {
System.out.println("猫吃肉");
}
}
class Rabbit implements Eatable{
@Override
public void eat() {
System.out.println("兔子吃草");
}
}
class Animal{
public static void eat(Eatable eatable){
eatable.eat();
}
}
class Main{
public static void main(String[] args) {
Animal.eat(new Cat());
Animal.eat(new Rabbit());
}
}
6.7 abstract类与接口的比较
- abstract 类可接口都可以有 abstract方法
- 接口中只能有常量,不能有变量,抽象类可以有变量,也可以有常量
- 抽象类中可以有非抽象方法,但是接口不可以
6.8 使用抽象类还是接口?
- 如果某个问题需要通过继承解决,也就是说需要从写父类方法时,还要继承一些父类的特性,那么我们就应该使用抽象类。
- 否则就使用接口
为什么有了抽象类还要有接口?
- 因为Java是单继承语言,抽象类抽象颗粒细度难以把控,所以引入了接口。
- 接口是更高级别的抽象,通过多接口实现可以更好的把控颗粒细度。
举个栗子
public interface Flyable {
void fly();
}
interface Swimmable{
void swim();
}
class Brid implements Flyable{
@Override
public void fly() {
System.out.println("小鸟会飞");
}
}
class Fish implements Swimmable{
@Override
public void swim() {
System.out.println("鱼会游泳");
}
}
6.9 面向接口编程
现在学了接口来对前面的 笔芯 案例 改造下,同样要满足 ”开闭原则“
class Refill{
private String color;
public Refill(String color) {
this.color = color;
}
public void w(){
System.out.println("我能书写"+color);
}
}
interface Writable {
void write(Refill refill);
}
public class Pen implements Writable{
@Override
public void write(Refill refill) {
refill.w();
}
}
class Test{
public static void main(String[] args) {
Pen pen = new Pen();
pen.write(new Refill("红色"));
pen.write(new Refill("蓝色"));
}
}
我能书写红色
我能书写蓝色
6.10 小结
- 接口的接口体中可以有常量和abstract方法
- 和类一样,接口也是Java中重要的引用数据类型,接口中只能存放实现接口类的实例对象引用
- 当接口存放了实现类的对象引用时,接口调用类实现写接口方法称之为接口回调
- 借助接口回调可以实现多态性
- 在设计多态程序时,要熟练使用回调技术以及面向接口编程的思想,以实现”开闭原则”