接口(一):
什么是接口?接口是怎么来的?
1、抽象类是从多个类中抽象出来的模板,如果将这种抽象进行的更彻底,则可以提炼出一种更加特殊的“抽象类”:接口(interface)
2、接口里所有方法都是抽象方法,不能包含普通方法(Java8之前)
3、接口定义了某一批类需要遵守的规范(通过接口内定义的一堆抽象方法),接口并不关心这些子类内部方法的具体实现,只规定这些类必须实现哪些方法
所以:接口是从多个类中抽象出来的一种规范,接口不提供任何实现,接口体现的是规范和实现分离的设计哲学
4、让规范和实现分离正是接口的好处,让软件系统的各组件之间面向接口耦合,是一种松耦合的设计。
例如:一块主机板上提供了PCI插槽,只要一块显卡遵守该PCI接口规范,就可以插入该PCI插槽,与主机板正常通信,至于这块主板是哪个厂家生产的,内部是如何实现的,主板无需关心(主板插槽PCI规范就相当于接口内定义的一批抽象方法,显卡相当于实现该接口的类,显卡遵守PCI规范相当于该子类按照接口规定的抽象方法,挨个的去实现了这些方法,但至于方法内具体实现规则,接口并不关心,就像主板并不关心显卡内部是怎么制造的一样)
类似的:软件设计的各模块之间,也应该采用这种面向接口的耦合,尽量降低模块之间的耦合,为系统提供更好的可扩展性和可维护性
因此:接口的定义是多个类共同的公共行为规范,这些行为是与外部交流的通道,这就意味着接口里通常定义一组公用方法
Java8中接口的定义:
1、和类定义不同,接口定义不再使用class关键字,而是使用 interface 关键字,接口定义的语法如下:
[修饰符] interface 接口名 extends 父接口1,父接口2,...{ 零个到多个常量定义; 零个到多个抽象方法定义; 零个到多个内部类、接口、枚举定义; 零个到多个默认方法或类方法定义; }
对上面语法的详细说明:
1、修饰符可以是 public 或者省略,如果省略,则采用包权限访问控制符
2、接口名称与类名称采用相同的命名规则,仅从语法的语义看,接口名称只要是合法的标识符即可,如果遵守Java 可读性程序规范,接口名称应该是多个有意义的单词组合,每个单词首字符大写
3、一个接口可以有多个直接父接口,但接口只能继承接口,不能继承类
4、上面的定义接口语法中,只有在Java8以上的版本中,接口内才可以定义默认方法,类方法,在Java8以前的版本中,接口内只能定义抽象方法,不能定义其它方法
总结:
1、因为接口是一种规范,所以接口内不能定义初始化块、构造器
2、接口可以包含成员变量,但只能是静态常量
3、接口可以包含方法,但只能是抽象方法、默认方法、类方法
4、接口可以包含内部类,但只能是接口、枚举
5、因为接口定义的是一种多个类的行为规范,所以接口内定义的所有成员,都是 public 访问权限,因此定义接口成员时,可以省略 public 修饰符
6、因为接口内定义的成员变量 必须是静态常量,所以定义成员变量时前面的 public static final 是固定的,所以可以省略该固定三个关键字,系统会自动为定义的成员变量加上 public static final
7、因为接口里没有构造器、初始化块等,所以定义的所有成员变量必须赋初始值
8、因为接口里定义的方法只能是抽象方法、默认方法或类方法,所以所有定义的抽象方法中,前面可以省略 public abstract 这俩关键字,系统会默认给加上;所有定义的默认方法必须用 default 修饰, 类方法必须用 static修饰,必须有方法体
9、从某个角度看,接口是一种特殊的类,因此一个Java文件里最多只能有一个 public 类型接口,并且该源文件名字必须与 public 类型接口相同
定义一个接口 代码:
package zd; public interface InterfaceOutPut{ //-定义一个常量 公共、静态、不可变、赋初始值 public static final int a=20; //-定义两个抽象方法 public abstract void Out(); public abstract String getData(String mes); //-定义两个默认方法,必须用default修饰 public default void print(String... mes){ for(String str:mes){ System.out.println(str); } } public default void test(){ System.out.println("接口中的默认方法!"); } //-定义一个类方法,必须用static 修饰 public static String staticTest(){ return "接口中的类方法!"; } }
定义一个类,调用该接口中的方法与成员变量;
package zdy; public class InterfaceOutPutFieldTest{ public static void main(String[] args){ //-调用另一个包中的接口常量 System.out.println(zd.InterfaceOutPut.a); //-给另一个包中的接口常量重新赋值 编译错误 因为是final 类型 //zd.InterfaceOutPut.a=25; //-调用另一个包中的接口 类方法 System.out.println(zd.InterfaceOutPut.staticTest()); //-调用另一个包中的接口 默认方法 编译报错 静态方法不能访问非静态方法 //zd.InterfaceOutPut.test(); } }
运行结果: