Java--接口
前言
理解好了抽象的概念,进一步学习接口。
接口的设计弥补了Java不能多继承的缺陷。
关于接口
可以将接口理解为:多个类的公共规范。
接口是一种引用数据类型,最重要的内容就是其中的抽象方法。
接口的定义格式:
1 | public interface 接口名称 { |
在Java7中,接口可以包含:
- 常量(定义后不可更改)
- 抽象方法(abstract)
在Java8中,又可以定义:
- 默认方法(default)
- 静态方法(static)
在Java9中,还可以包含:
- 私有方法(private)
注意:接口是没有静态代码块或者构造方法的。
使用
基本使用
接口使用规范:
-
接口不能直接使用,必须有一个实现类来实现该接口
1
2
3public class 实现类名称 implements 接口名称 {
// ...
} -
接口的实现类必须覆盖重写(实现)接口中所有的抽象方法
-
创建实现类的对象,进行使用
在定义接口的抽象方法时需要注意格式:
public abstract 返回值类型 方法名称(参数列表);
- 接口当中的抽象方法,修饰符必须是两个固定的关键字:
public abstract
- 这两个关键字修饰符,可以选择性地省略(省略后仍为抽象方法)
定义接口InterfaceDemo
:
1 | public interface InterfaceDemo { |
定义接口实现类InterfaceDemoImpl
:
1 | public class InterfaceDemoImpl implements InterfaceDemo { |
定义使用类Demo
1 | public class Demo { |
结果如下:
1 | 第一个方法 |
默认方法
接口中的默认方法,可以解决接口升级的问题。
1 | public default 返回值类型 方法名称(参数列表) { |
假设一个项目已经投入使用,这时在接口升级中准备添加一个新的方法,但是该接口的所有实现类都需要重写新的方法。如此一来升级维护成本太大,所以在Java8之后,允许接口定义默认方法,免去接口实现类重写的麻烦。
- 实现类可以重写接口中定义的默认方法
- 实现类可以直接使用接口中定义的默认方法
定义接口InterfaceDemo
:
1 | public interface InterfaceDemo { |
定义接口实现类InterfaceDemoImpl
:
1 | public class InterfaceDemoImpl implements InterfaceDemo { |
定义使用类Demo
:
1 | public class Demo { |
结果如下:
1 | 重写接口的抽象方法 |
静态方法
Java8后还允许接口定义静态方法,格式如下:。
1 | public static 返回值类型 方法名称(参数列表) { |
注意:
- 必须有
public
关键字修饰,不然其他类无法访问 - 正确用法:不可以通过接口的实现类来调用静态方法,直接按照调用格式使用:
接口名称.静态方法名(参数);
定义接口InterfaceDemo
:
1 | public interface InterfaceDemo { |
定义使用类Demo
:
1 | public class Demo { |
结果如下:
1 | 接口的静态方法 |
常量
接口当中也可以定义成员变量,但是必须使用public static final
三个关键字进行修饰,从效果上看,这其实就是接口的常量。
1 | public static final 数据类型 常量名称 = 数据值; |
注意:
- 接口当中的常量,可以省略
public static final
。(省略不写效果一样) - 接口当中的常量,必须进行赋值。
- 推荐接口常量的命名规则:使用完全大写的字母,用下划线进行分隔。
定义接口InterfaceDemo
:
1 | public interface InterfaceDemo { |
定义使用类Demo
:
1 | public class Demo { |
结果如下:
1 | 接口常量一 |
接口的多实现
一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
1 | public class InterfaceImpl implements InterfaceA, InterfaceB { |
使用时需要注意:
- 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可;
- 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类;
- 如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写;
- 一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法(可以不用重写)
定义接口InterfaceDemoA
:
1 | public interface InterfaceDemoA { |
定义接口InterfaceDemoB
:
1 | public interface InterfaceDemoB { |
定义父类Fu
:
1 | public class Fu { |
定义子类/接口实现类Zi
:
1 | public class Zi extends Fu implements InterfaceDemoA,InterfaceDemoB { |
定义使用类Demo
:
1 | public class Demo { |
结果如下:
1 | 重写接口A的方法 |
接口的多继承
接口与接口之间是多继承的。
1 | public interface InterfaceDemo extends InterfaceA, InterfaceB { |
使用时注意:
- 可以不用重写父接口的抽象方法(冲突也不要紧,因为实现类总要重写)
- 多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写
定义父接口InterfaceA
:
1 | public interface InterfaceA { |
定义父接口InterfaceB
:
1 | public interface InterfaceB { |
定义子接口InterfaceDemo
:
1 | public interface InterfaceDemo extends InterfaceA, InterfaceB { |
定义子接口实现类InterfaceDemoImpl
:
1 | public class InterfaceDemoImpl implements InterfaceDemo { |
定义实用类Demo
:
1 | public class Demo { |
结果如下:
1
2
3
4
5
重写父接口A的方法
重写父接口B的方法
重写子接口的方法
重写父接口的重名方法
重写父接口默认重名方法
1 | 重写父接口A的方法 |
后记
无