基本介绍
接口是一种公共规范,最重要的是抽象方法
一、Java 7
- 抽象方法:[public] [abstract]
- 常量:[public] [static] [final],大写+下划线
// 抽象方法
public abstract 返回值类型 方法名 (参数列表){方法体}
// 常量
// final修饰类不能被继承,修饰方法不能被隐藏,修饰变量不能被改变
// 成员变量有默认初始化值,必须声明时赋初值或构造方法赋值,接口没有构造方法
public static final 数据类型 常量名称 = 数据值;
二、Java 8
增加:默认方法[public] default,静态方法[public] static
解决接口升级的问题,已有接口中新增抽象方法,其实现类会受到影响
// 默认方法 【接口名.super.方法名】
public default 返回值类型 方法名(参数列表){方法体}
// 静态方法 【接口名.方法名】
public static 返回值类型 方法名(参数列表){方法体}
-
默认方法自动被实现类/子接口继承,可以覆盖重写
提供一个常用实现,避免实现类重复编写相同的代码
-
静态方法必须通过接口名调用,不能通过对象名调用
提供与接口相关的工具方法,被实现类或其他类直接调用
/**
* 如果允许接口实例或实现类实例调用静态方法,可能引起歧义
* 一个类可以同时实现多个接口,多个接口中的静态方法可能重名
*/
MyInterface.methodStatic();
MyInterface myInterface = new MyInterfaceImpl();
// myInterface.methodStatic(); // 标红报错 上转型对象
MyInterfaceImpl myInterfaceimpl = new MyInterfaceImpl();
// myInterfaceimpl.methodStatic(); // 标红报错 实现类对象
三、Java 9
增加:私有方法(普通私有、静态私有)
解决方法中代码重复问题,且保证该方法不被实现类访问到
- 普通私有用来解决默认方法之间的共性抽取
- 静态私有用来解决静态方法之间的共性抽取
// 普通私有方法
private 返回值类型 方法名 (参数列表){方法体}
// 静态私有方法
private static 返回值类型 方法名 (参数列表){方法体}
注意事项
1、不能直接new接口对象
覆盖重写接口中所有的抽象方法,否则该实现类必须是抽象类
// 接口
interface MyInterface {
public abstract void method();
}
// 子类
public class MyInterfaceImpl implements MyInterface {
@Override
public void method() {
System.out.println("MyInterfaceImpl...");
}
}
2、接口没有构造方法,不能定义静态代码块
3、一个类可以同时实现多个接口(类与接口是多实现)
重写的接口方法,一定显示使用public修饰(不能降低访问权限)
方法签名:方法名+参数列表,用来区分不同方法的标识符【重名】
- 默认方法重名,实现类必须覆盖重写
- 抽象方法重名,实现类覆盖重写,或实现类是抽象类
- 静态方法重名没关系,静态成员属于接口,必须通过接口名调用
// MyInterfaceA
public interface MyInterfaceA {
public abstract void methodAbs(); // 抽象方法
public default void methodDef() {
System.out.println("methodDef in A..."); // 默认方法
}
public static void methodSta(){
System.out.println("methodSta in A..."); // 静态方法
}
}
// MyInterfaceB
public interface MyInterfaceB {
public abstract void methodAbs(); // 抽象方法
public default void methodDef() {
System.out.println("methodDef in B..."); // 默认方法
}
public static void methodSta(){
System.out.println("methodSta in B..."); // 静态方法
}
}
// 实现类,同时实现接口A、接口B
public class MyInterfaceIml implements MyInterfaceA, MyInterfaceB { // 抽象类
// 默认方法重名,实现类必须覆盖重写
@Override
public void methodDefault() {
}
// 抽象方法重名,实现类覆盖重写,或实现类是抽象类
@Override
public void methodAbs() {
}
}
4、一个接口可以同时继承多个接口(接口与接口是多继承)
- 默认方法重名,子接口必须覆盖重写,且带着default关键字
- 抽象方法重名没关系,接口中主要是抽象方法
- 静态方法重名没关系,静态成员属于接口,必须通过接口名调用
// InterfaceA
public interface InterfaceA {
// 抽象方法
public abstract void methodA();
public abstract void methodAbs();
// 默认方法
public default void methodDef() {
System.out.println("methodDef in A...");
}
}
// InterfaceB
public interface InterfaceB {
// 抽象方法
public abstract void methodB();
public abstract void methodAbs();
// 默认方法
public default void methodDef() {
System.out.println("methodDef in B...");
}
}
// 子接口同时继承接口A、接口B
public interface InterfaceZi extends InterfaceA, InterfaceB {
// 子接口中有三个抽象方法,一个默认方法
@Override
default void methodA() {
}
@Override
default void methodB() {
}
@Override // 接口A、接口B重名抽象方法
default void methodAbs() {
}
// 默认方法重名,子接口必须覆盖重写,且带着default关键字
@Override
default void methodDef() {
}
}
5、一个类可以同时继承父类并实现接口
(1)父类的实例方法和接口的默认方法重名
- 若子类没有重写方法,编译不会报错,优先调用父类中的方法
- 若子类重写了该方法,相当于同时重写父类以及接口中的方法,调用的是子类重写后的方法
// Fu
public class Fu {
public void methodDef() {
System.out.println("methodDef in Fu...");
}
}
// MyInterfaceA
public interface MyInterfaceA {
// 默认方法
public default void methodDef() {
System.out.println("methodDef in A...");
}
}
// MyInterfaceB
public interface MyInterfaceB {
// 默认方法
public default void methodDef() {
System.out.println("methodDef in B...");
}
}
// 子类继承父类,同时实现接口A、接口B
public class Zi extends Fu implements MyInterfaceA, MyInterfaceB {
@Override
public void methodDef() {
// 基于父类的实例方法
// super.methodDef();
// 基于接口的默认方法
// 不建议,默认方法的目的是为了提供一个常用实现而不是被覆盖
// MyInterfaceA.super.methodDef();
// MyInterfaceB.super.methodDef();
// 提供自己的全新实现
System.out.println("methodDef in Zi...");
}
}
// 测试类
public class Test {
public static void main(String[] args) {
Zi zi = new Zi();
zi.methodDef(); // 重写了:methodDef in Zi...
// 没重写:methodDef in Fu...
}
}