什么是接口
接口是一种规范,符合这个接口的类的一组需求。
在 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 {
@Override
public void ParentAbstractMethod1() {
}
@Override
public void ParentAbstractMethod2() {
}
}
interface ParentInter1 {
void ParentAbstractMethod1();
}
interface ParentInter2 {
void ParentAbstractMethod2();
}
发生冲突分为以下几种情况。
抽象方法冲突
如果父类接口中定义了相同的抽象方法,只需重写一个即可 。
public class Test implements ParentInter1, ParentInter2 {
@Override
public void ParentAbstractMethod() {
}
}
interface ParentInter1 {
void ParentAbstractMethod();
}
interface ParentInter2 {
void ParentAbstractMethod();
}
默认方法冲突
如果两个或多个独立定义的默认方法冲突,则必须显式覆盖超类型的方法。
可以通过 接口名.super.冲突的默认方法
来访问冲突的默认方法。
public class Test implements ParentInter1, ParentInter2 {
@Override
public 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");
}
}
私有方法冲突
不冲突,因为不会继承。
参考: