什么是接口
接口是一种规范,符合这个接口的类的一组需求。
在 Java 中使用 interface 关键字定义一个接口。
public interface Ineter {void method();....}
在 Java 中接口是一个类似于类的引用类型,它只能包含常量、方法签名、默认方法和嵌套类型。方法体仅适用于默认方法和静态方法。接口不能实例化,只能通过类 implemented 或通过其他接口 extended。
接口可以包含什么
三个 JDK 版本的接口设计功能对比。
| Java 7 | Java 8 | Java 9 | 
|---|---|---|
| 常量 | 常量 | 常量 | 
| 抽象方法 | 抽象方法 | 抽象方法 | 
| 默认方法 | 默认方法 | |
| 公共静态方法 | 公共静态方法 | |
| 私有方法(非私有静态方法) | ||
| 私有静态方法 | 
抽象方法
接口可以包含抽象方法,这是最基本的。因为接口定义的所有方法默认都是 public static 的,所以可以省略这些修饰符。
public interface Inter {void abstractMenthod1();String abstractMethod2();....}
常量
接口可以包含常量,所有常量值默认都是 public static final ,所以可以省略这些修饰符。
public interface Inter {int a = 1;public static final String s = "test";...}
默认方法
使用默认方法是为了方便拓展已有的接口,如果没有默认方法,加入给 JDK 中的某个接口添加一个新的抽象方法,那么所有实现了该接口的类都得修改,影响非常大。
使用 default 关键字定义,默认方法是默认都是 public(也只能是 public)  ,包含方法体。
public interface Inter {default String defaultMethod1() {return "this is defaultMethod1";}default public String defaultMethod2() {return "this is defaultMethod2";}...}
静态方法
接口的静态方法可以是公共的(public)和私有的(private)默认是 public,其中私有静态方法是 Java 9 新增的特性,静态方法是属于接口的。私有静态方法只能被接口中的默认方法、其他的私有静态方法、公共静态方法、私有方法(非私有静态方法)访问。
interface Inter {public static void publicStaticMethod() {System.out.println("this is publicStaticMethod");}public static void accessPrivateStaticMethodByPubicStaticMethod() {privateStaticMethod();}private static void privateStaticMethod() {System.out.println("this is privateStaticMethod");}private void accessPrivateStaticMethodByPrivateMethod() {privateStaticMethod();}default void accessStaticMethod() {privateStaticMethod();}}
私有方法(非私有静态方法)
这是 Java 9 新增的特性,用于解决多个默认方法之间重复代码问题。私有方法必须有方法体。
interface Inter {default void defaultMethod1() {commonCode();System.out.println("this is defaultMethod1.");}default void defaultMethod2() {commonCode();System.out.println("this is defaultMethod2.");}private void commonCode() {System.out.println("this is commonCode.");}}
嵌套类型
接口可以嵌套在另外一个接口里面,类也可以嵌套在接口里面。(了解即可,这个特性没有人使用的。。。)
interface Inter {default void defaultMethod() {System.out.println("defaultMethod");}interface nestedInter {}class nestedClass {}}
接口的实现
一个类可以实现一个或多个接口,使用关键字 implements 定义。
public class Test implements ParentInter1, ParentInter2 {@Overridepublic void ParentAbstractMethod1() {}@Overridepublic void ParentAbstractMethod2() {}}interface ParentInter1 {void ParentAbstractMethod1();}interface ParentInter2 {void ParentAbstractMethod2();}
发生冲突分为以下几种情况。
抽象方法冲突
如果父类接口中定义了相同的抽象方法,只需重写一个即可 。
public class Test implements ParentInter1, ParentInter2 {@Overridepublic void ParentAbstractMethod() {}}interface ParentInter1 {void ParentAbstractMethod();}interface ParentInter2 {void ParentAbstractMethod();}
默认方法冲突
如果两个或多个独立定义的默认方法冲突,则必须显式覆盖超类型的方法。
可以通过 接口名.super.冲突的默认方法 来访问冲突的默认方法。
public class Test implements ParentInter1, ParentInter2 {@Overridepublic void ParentAbstractMethod() {ParentInter1.super.ParentAbstractMethod();ParentInter2.super.ParentAbstractMethod();}}interface ParentInter1 {default void ParentAbstractMethod() {System.out.println("this is ParentAbstractMethod1");}}interface ParentInter2 {default void ParentAbstractMethod() {System.out.println("this is ParenAbstractMethod2");}}
还有另外一种情况
已被其他候选覆盖的方法将被忽略。当超类型共享公共的祖先时,可能会出现这种情况。
public class Test implements ParentInter2, ParentInter3 {public static void main(String[] args) {Test t = new Test();t.ParentAbstractMethod(); // this is ParenAbstractMethod2}}interface ParentInter1 {default void ParentAbstractMethod() {System.out.println("this is ParentAbstractMethod1");}}interface ParentInter2 extends ParentInter1 {default void ParentAbstractMethod() {System.out.println("this is ParenAbstractMethod2");}}interface ParentInter3 extends ParentInter1 {}
默认方法与实例方法冲突
实例方法优于默认方法。
public class Test extends ParentClass implements ParentInter {public static void main(String[] args) {Test t = new Test();t.method(); // this is ParentClass method}}interface ParentInter {default void method() {System.out.println("this is ParentInter1 method");}}class ParentClass {public void method() {System.out.println("this is ParentClass method");}}
接口与接口之间的关系
接口可以拓展一个或多个接口,使用关键字 extends 关键字定义。
interface ChildInter extends ParentInter1, ParentInter2 {}interface ParentInter1 {}interface ParentInter2 {}
发生冲突分为以下几种情况。
常量冲突
不能被继承,必须显式覆盖。
public class Test {public static void main(String[] args) {System.out.println(ChildInter.s); // ChildInter}}interface ChildInter extends ParentInter1, ParentInter2 {String s = "ChildInter";}interface ParentInter1 {String s = "ParentInter1";}interface ParentInter2 {String s = "ParentInter2";}
静态方法(公共和私有)冲突
不冲突,静态方法属于类的不发生继承。
public class Test {public static void main(String[] args) {// ChildInter.staticMethod(); 因为不继承,所以不能访问。}}interface ChildInter extends ParentInter1, ParentInter2 {}interface ParentInter1 {static void staticMethod() {System.out.println("this is ParentInter1");}}interface ParentInter2 {static void staticMethod() {System.out.println("this is ParentInter2");}}
私有方法冲突
不冲突,因为不会继承。
参考:
