Java基础---接口
前言
理解好了抽象的概念,进一步学习接口
接口的设计弥补了Java不能多继承的缺陷
本篇文章将介绍Java接口的相关内容
关于接口
可以将接口理解为:多个类的公共规范
接口是一种引用数据类型,最重要的内容就是其中的抽象方法
接口的定义格式:
public interface 接口名称 {
// 接口内容
}
在Java7中,接口可以包含:
常量
(定义后不可更改)抽象方法
(abstract
)
在Java8中,又可以定义:
默认方法
(default
)静态方法
(static
)
在Java9中,还可以包含:
私有方法
(private
)
注意:接口是没有静态代码块或者构造方法的
使用
基本使用
接口使用规范:
- 接口不能直接使用,必须有一个
实现类
来实现该接口
public class 实现类名称 implements 接口名称 {
// ...
}
- 接口的实现类必须
覆盖重写
(实现)接口中所有的抽象方法
- 创建
实现类
的对象,进行使用
在定义接口的抽象方法时需要注意格式:
public abstract 返回值类型 方法名称(参数列表);
接口当中的抽象方法,修饰符必须是两个固定的关键字:
public abstract
这两个关键字修饰符,可以
选择性地省略
(省略后仍为抽象方法)
定义接口InterfaceDemo
:
public interface InterfaceDemo {
public abstract void method1();
void method2();
}
定义接口实现类InterfaceDemoImpl
:
public class InterfaceDemoImpl implements InterfaceDemo {
@Override
public void method1() {
System.out.println("第一个方法");
}
@Override
public void method2() {
System.out.println("第二个方法");
}
}
定义使用类Demo
public class Demo {
public static void main(String[] args) {
InterfaceDemoImpl Demo = new InterfaceDemoImpl();
Demo.method1();
Demo.method2();
}
}
结果如下:
第一个方法
第二个方法
默认方法
接口中的默认方法,可以解决接口升级
的问题
public default 返回值类型 方法名称(参数列表) {
方法体
}
假设一个项目已经投入使用,这时在接口升级中准备添加一个新的方法,但是该接口的所有实现类都需要重写新的方法。如此一来升级维护成本太大,所以在Java8之后,允许接口定义默认方法,免去接口实现类重写的麻烦
实现类可以重写接口中定义的默认方法
实现类可以直接使用接口中定义的默认方法
定义接口InterfaceDemo
:
public interface InterfaceDemo {
public abstract void method();
public default void method1() {
System.out.println("接口默认方法一");
}
default void method2() {
System.out.println("接口默认方法二");
}
}
定义接口实现类InterfaceDemoImpl
:
public class InterfaceDemoImpl implements InterfaceDemo {
@Override
public void method() {
System.out.println("重写接口的抽象方法");
}
@Override
public void method1() {
System.out.println("重写接口的默认方法一");
}
}
定义使用类Demo
:
public class Demo {
public static void main(String[] args) {
InterfaceDemoImpl Demo = new InterfaceDemoImpl();
Demo.method();
Demo.method1();
Demo.method2();
}
}
结果如下:
重写接口的抽象方法
重写接口的默认方法一
接口默认方法二
静态方法
Java8后还允许接口定义静态方法
,格式如下:
public static 返回值类型 方法名称(参数列表) {
方法体
}
注意:
必须有
public
关键字修饰,不然其他类无法访问正确用法:不可以通过接口的实现类来调用静态方法,直接按照调用格式使用:
接口名称.静态方法名(参数);
定义接口InterfaceDemo
:
public interface InterfaceDemo {
public static void method() {
System.out.println("接口的静态方法");
}
}
定义使用类Demo
:
public class Demo {
public static void main(String[] args) {
InterfaceDemo.method();
}
}
结果如下:
接口的静态方法
常量
接口当中也可以定义成员变量,但是必须使用public static final
三个关键字进行修饰,从效果上看,这其实就是接口的常量
public static final 数据类型 常量名称 = 数据值;
注意:
接口当中的常量,可以省略
public static final
(省略不写效果一样)接口当中的常量,
必须
进行赋值
推荐接口常量的
命名规则
:使用完全大写的字母,用下划线进行分隔
定义接口InterfaceDemo
:
public interface InterfaceDemo {
public static final String STR1 = "接口常量一";
String STR2 = "接口常量二";
}
定义使用类Demo
:
public class Demo {
public static void main(String[] args) {
System.out.println(InterfaceDemo.STR1);
System.out.println(InterfaceDemo.STR2);
}
}
结果如下:
接口常量一
接口常量二
接口的多实现
一个类的直接父类是唯一的
,但是一个类可以同时实现多个接口
public class InterfaceImpl implements InterfaceA, InterfaceB {
// 覆盖重写所有抽象方法
}
使用时需要注意
:
- 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可
- 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类
- 如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写
- 一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法(可以不用重写)
定义接口InterfaceDemoA
:
public interface InterfaceDemoA {
public abstract void methodA();
public default void method() {
System.out.println("接口A的重名默认方法");
}
}
定义接口InterfaceDemoB
:
public interface InterfaceDemoB {
public abstract void methodB();
public default void method() {
System.out.println("接口B的重名默认方法");
}
}
定义父类Father
:
public class Father {
public void method_Father() {
System.out.println("父类方法");
}
public void method() {
System.out.println("父类重名方法");
}
}
定义子类/接口实现类Son
:
public class Son extends Father implements InterfaceDemoA,InterfaceDemoB {
@Override
public void methodA() {
System.out.println("重写接口A的方法");
}
@Override
public void methodB() {
System.out.println("重写接口B的方法");
}
@Override
public void method() {
System.out.println("重写接口和父类的重名方法");
}
}
定义使用类Demo
:
public class Demo {
public static void main(String[] args) {
Son son = new Son();
son.methodA();
son.methodB();
son.method_Father();
son.method();
}
}
结果如下:
重写接口A的方法
重写接口B的方法
父类方法
重写接口和父类的重名方法
接口的多继承
接口与接口
之间是多继承
的
public interface InterfaceDemo extends InterfaceA, InterfaceB {
// 覆盖重写所有冲突的默认方法
}
使用时注意:
- 可以不用重写父接口的抽象方法(冲突也不要紧,因为实现类总要重写)
- 多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写
定义父接口InterfaceA
:
public interface InterfaceA {
public abstract void methodA();
public abstract void methodCommon();
public default void methodDefault() {
System.out.println("父接口A的重名默认方法");
}
}
定义父接口InterfaceB
:
public interface InterfaceB {
public abstract void methodB();
public abstract void methodCommon();
public default void methodDefault() {
System.out.println("父接口B的重名默认方法");
}
}
定义子接口InterfaceDemo
:
public interface InterfaceDemo extends InterfaceA, InterfaceB {
public abstract void methodC();
@Override
public default void methodDefault() {
System.out.println("重写父接口默认重名方法");
}
}
定义子接口实现类InterfaceDemoImpl
:
public class InterfaceDemoImpl implements InterfaceDemo {
@Override
public void methodA() {
System.out.println("重写父接口A的方法");
}
@Override
public void methodB() {
System.out.println("重写父接口B的方法");
}
@Override
public void methodC() {
System.out.println("重写子接口的方法");
}
@Override
public void methodCommon() {
System.out.println("重写父接口的重名方法");
}
}
定义实现类Demo
:
public class Demo {
public static void main(String[] args) {
InterfaceDemoImpl Demo = new InterfaceDemoImpl();
Demo.methodA();
Demo.methodB();
Demo.methodC();
Demo.methodCommon();
Demo.methodDefault();
}
}
结果如下:
重写父接口A的方法
重写父接口B的方法
重写子接口的方法
重写父接口的重名方法
重写父接口默认重名方法