目录
接口的概念
接口的作用是非常丰富的,接口往往与设计模式接口在一块。让规范和实现相分离,让软件的各组件之间面向接口耦合。
接口的概念: - 可以认为接口是一种“彻底”的抽象类
接口:是从多个相似的类中抽取出来的一种规范。接口体现的是规范
接口的体现:通信规范
Java 8 中接口的定义
接口定义的语法
[修饰符] interface 接口名 extends 父接口1,父接口2,……{
// 0 ~ N 个 Field 定义
// 0 ~ N 个 抽象方法
// 0 ~ N 个 内部类、内部接口、内部枚举定义
}
修饰符:public或省略
接口名:多个单词拼接而成,且每个单词的首字母大写。推荐接口用“形容词”。
(因为C#推荐接口名以I开头,Java程序员沿用了这种方法)
【注意】
- 接口不能有构造器,也不能有初始化。
- 接口里的Field默认有三种修饰符:public static final(不论程序员写或者不写,他都存在)
- 接口里的方法默认有两个:public abstract(不论程序员写或者不写,他都存在)
- 接口里的内部类、内部接口、内部枚举,默认也有2个修饰符:public static(不论程序员写或者不写,他都存在)
- 一个接口可以有N个直接父类接口
- Java 8允许在接口中设置默认方法,但默认方法一定要 default 修饰,另外该方法不能用 static 修饰;而类方法只能有static修饰,该方法不能由default修饰。
Output.java
public interface Output {
//接口里定义的成员变量均为常量
int MAX_CACHE_LINE = 50 ;
//以上相当于public static final int MAX_CACHE_LINE = 50 ;
//往接口里定义抽象方法,且抽象方法只能用public修饰
void out();
void getData(String msg);
//在接口中定义默认方法,需要使用default修饰
default void print(String... msgs) {
for(String msg:msgs) {
System.out.println(msg);
}
}
default void test() {
System.out.println("默认的test()方法");
}
//在接口中定义类方法,需要static修饰
static String staticTest() {
return "function in the static class";
}
}
OutputTest.java
public class OutputFieldTest {
public static void main(String[] args) {
//访问另一个包中的Output接口中飞MAX_CACHE_LINE
System.out.println(Output.MAX_CACHE_LINE);
//在这里给MAX_CACHE_LINE重新赋值会出现编译异常
System.out.println(Output.staticTest());
}
}
/*
50
function in the static class
*/
接口的继承
一个接口可以有N个直接父接口,这是与类继承的不同点。
//格式
interface Ia{}
interface Ib{}
interface Ic extends Ia,Ib{}
使用接口
有了接口:
- 接口可用于定义变量,也可用于强制类型转换
- 接口不能直接创建实例,但可以调用接口中的常量
- 接口最大用途就是供其他类来实现自己(是不是很像抽象方法?)
implements实现一个或N个接口。(体会类的继承和接口继承)
[修饰符] class 类名 extends 父类 implements 父接口1,父接口2,……{
// 0 ~ N 个 Field 定义
// 0 ~ N 个 抽象方法
// 0 ~ N 个 内部类、内部接口、内部枚举定义
}
当一个类实现接口之后:实现类要么为接口的的所有抽象方法提供实现。否则你的实现类也只能是抽象类。接口主要实在“面向接口编程”时提供更灵活的机制。(可以吧实现接口理解为一种特殊的继承,相当于实现类继承了一个彻底抽象的类)
interface Product{
//这是一个接口中的抽象方法,全部是public abstract int getProduceTime()
int getProduceTime();
}
public class Printer implements Output,Product{
private String[] printData = new String[MAX_CACHE_LINE];
//用以记录当前需要打印的作业数
private int printNum = 0;
//作用:打印函数
public void out() {
//若有作业,继续打印
while(printNum>0) {
System.out.println("打印机打印"+printData[0]);
//所有字符向前挪1位
/*
* System.arraycop的API:
* public static void arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length)
*将指定源数组中的数组从指定位置复制到目标数组的指定位置。
* */
System.arraycopy(printData, 1, printData, 0, --printNum);
}
}
//作用:判断打印的字符串是否超过规定值
public void getData(String msg) {
if(printNum>=MAX_CACHE_LINE) {
System.out.println("输出队列已满,添加失败");
}else {
//把打印数据添加到队列里,已保存数据的数量+1
printData[printNum++]=msg;
}
}
public int getProduceTime() {
return 45;
}
public static void main(String[] args) {
//向上转型,编译时o是Output类型,运行时o时Printer类型
Output o = new Printer();
o.getData("我在加强Java的基础学习");
o.getData("学习的有点慢");
//开始打印
o.out();
//调用Output里的print(String... msgs)方法
o.print("孙悟空","猪八戒","沙和尚");
//创建一个Printer对象,当成Product使用
Product p = new Printer();
System.out.println(p.getProduceTime());
//接口不能显式继承任何类,但是所有接口的引用类型都是可以赋值给Object
Object obj = p;
}
}
/*输出的内容:
* 打印机打印我在加强Java的基础学习
打印机打印学习的有点慢
孙悟空
猪八戒
沙和尚
45
*
* */
接口和抽象类
接口对于实现者而言,规定了必须向外提供哪些服务;对调用者而言,规定了可以调用哪些服务
【接口和抽象类的异同】
相似
- 都可以包含抽象方法
- 都不能创建实例
- 子类继承抽象类、实现了接口,都要求实现所有的方法,否则子类也只能是抽象类
区别
- 接口里只能有抽象方法,但抽象类可以没有抽象方法,只包含普通方法
- 接口里不能定义静态方法(为什么?),但抽象类中可以包含静态方法
- 接口里的 Field 总有总有 public static final ,但抽象类中的 Field 完全可以是最普通的Field
- 接口不能包含构造器,但抽象类可以使用构造器
- 接口不能包含初始化块,但抽象类可包含初始化块
- 接口可以有多个直接的父接口,但是抽象类只能有一个父接口