目录
Java 接口
接口(interface)的概念
- 接口是一种更加特殊的抽象类,是抽象类的延伸!可以看作是纯粹的抽象类。
- 抽象类是从多个类中抽象出来的模板,接口则是将这种抽象类抽象的更彻底。
- 可以用于规范实现接口的类中必须实现接口中抽象方法。接口可以理解为一种契约 。简述:规范类必须实现的方法。
可以使用关键字interface定义接口:
package Yuan;
public interface DY { //修饰符只可以是public或者省略,省略就是同包访问接口,因为他是多个类共同的行为规范即为public。
public void dd();//没有方法体,无法定义具体实现,接口里是抽象方法
public void pp();
public void size();
int A = 5;//默认public static final int A = 5;接口里没有构造器和初始化块所以必须在定义时指定默认值 。可以为多个接口的实现类共享常量!!!
default boolean yyy() {//默认方法,可以有方法体,在接口中定义默认方法用default修饰
return true;//default修饰方法只能在接口中使用,在接口种被default标记的方法为普通方法
}
public static void ff(){//这个静态方法可以通过接口名称直接调用DY.ff();,同时允许 在实现类中重新定义.在接口中不能定义静态块 static{}!!!
System.out.println("接口中的静态方法!");
}
}
interface IDD{//和类相同 一个文件只能有一个public 接口和文件同名,其他接口类内可见
// 这个接口中没有包含任何抽象方法。如果一个接口中没有定义抽象方法,这种接口也叫做旗标接口、标志接口
}
接口的特点
- 抽象类可以不定义接口中的所有方法。
- 接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有抽象方法,否则就必须声明为抽象类。
- 接口没有构造方法。
- 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
- 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
- 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
- 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法)。
- 接口里可以包含内部类(包括内部接口、枚举)定义。
接口的作用
- 引入接口的作用在于隔离实现,规范和实现分离的设计哲学!
- 接口定义了一种规范(某一批类所需要遵循的规范)类是一种具体的实现体。
- 软件系统的各个组件模块之间面向接口耦合,这是一种松耦合设计,使程序有更好的可扩展性可维护性。
public void 出行(飞机类 a) {//该类和飞机类耦合了,因此该类此方法只能实现飞机类出行
System.out.println("飞机准备起飞。");
}
public void 出行(飞行属性 a) {//实现了飞行属性的类都可以,弱耦合!!!!!
System.out.println("出行成功");
}//可实现在接口的多个类进行更换
接口的使用
接口不能用于创建实例,但接口可以用于声明引用类型变量,直接使用,必须有对应的实现类 。
- 定义变量,也可用于进行强制类型转换
- 调用接口中定义的常量
- 被其他类实现
-
最佳软件开发实践:先定义接口规范调用方法,在使用抽象类实现接口定义公共方法,最后再定义具体子类实现所有的方法
package Yuan;
public interface 飞行属性 {//不能直接使用
public void 降落();
public void 匀速直线飞行();
public void 起飞();
}
package Yuan;
public class 飞机类 implements 飞行属性 {
public void 起飞() {
System.out.println("飞机准备起飞。");
}
public void 降落() {
System.out.println("飞机准备降落。");
}
public void 匀速直线飞行() {
System.out.println("飛機实现匀速直线飞行");
}
public static void main(String[] args) {
飞行属性 a = new 飞机类(); // 通过接口定义变量,使用具体类的实例,进行调用,因为变量是通过接口进行声明的,所以只能调用接口中声明的方法,
a.匀速直线飞行();
System.out.println(DY.A); //常量可以直接使用
System.out.println(new 飞机类().CC); //实现类也可以直接访问常量
}
}
接口的继承
接口完全支持多继承,
一个接口可以有多个直接的父接口,一个接口可以继承多个接口,
和类继承相似子接口扩展某个父接口会获得父接口定义的所有抽象方法和常量
package Yuan;
public interface IC extends IA, IB {
//接口的继承相当于继承
}
interface IAAA {
public default void pp() {
System.out.println("this is IA.pp() default");
}
public void dd();
public void ddd();
}
interface IBBB {
public default void pp() {
System.out.println("this is IB.pp() default");
}
public void ee();
}
class DDDD implements IBBB {
//类的实现相当于实现
public void pp() {
}
public void ee() {
}
public void ddd() {
System.out.println("asdasd");
}
}
class DEDE extends DDDD implements IAAA {//实现的是IAAA接口里面的ddd()方法可以继承DDDD而来
public void dd() {
}
}
- 接口的出现避免了单继承的局限性,这样定义C接口则拥有A+B的所有定义。
- 可以使用A和B接口以及父类D声明变量类型,直接new T。
- 但是约束时,用谁声明变量编译器系统识别就是谁这种类型,也就意味只能调用识别类型中的方法,不能调用其他方法 。
interface A {
public void p1();
}
interface B {
public void p2();
}
interface C extends A, B {
}
class D {
public void abc() {
}
}
class T extends D implements C {
public void p1() {
}
public void p2() {
}
D d = new T();// 这里只能直接调用abc方法,如果使用其他方法则需要进行类型转换
A a = new T();// 这里只能直接调用A接口中声明的方法p1
B b = new T();// 这里只能直接调用B接口中声明的方法p2 C c=new T();
}
关于default的接口实现问题
package Yuan;
public class ASD implements IAaaas, IBb {
public void pp() { //同时实现两个接口,一旦有同名方法就必须要在类中实现default方法,实现的是类中的
IBb.super.pp();
System.out.println("ASD的pp方法");
}
public void bb() {
}
public void aa() {
}
public static void main(String[] args) {
IAaaas aa = new ASD();
aa.pp(); //调用的是ASD的方法
ASD aaa = new ASD();
aaa.pp();//两种调用的都是ASD的方法,两个接口没有同名的default方法时,不用在类中写,直接类对象调用方法
}
}
interface IAaaas {
public default void pp() {
System.out.println("this is IA.pp() default");
}
public void aa();
}
interface IBb {
public default void pp() {
System.out.println("this is IB.pp() default");
}
public void bb();
}
代码运行的结果:
this is IB.pp() default
ASD的pp方法
this is IB.pp() default
ASD的pp方
类和接口可以写在一个.java文件内