1、接口
1.1 概述
- 概述:
- 从广义上讲: 接口就是对外提供的规则 (扩展功能,比如USB接口)
- 从狭义上:在Java里面指的是用interface修饰的东西
- 接口,是Java语言中另一种引用数据类型
- 是方法的集合 ,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了常量和方法
- 其中方法包含抽象方法 (JDK 7及以前),默认方法 和静态方法 (JDK 8),私有方法 (JDK 9)
- 接口的定义,它与定义类方式相似,但是使用
interface
关键字- 它也会被编译成.class文件,但一定要明确它并不是类
- 接口不是类,凡是类都有构造方法,接口没有构造方法,而是一种引用数据类型
- 接口的使用,几乎跟抽象类的用法一致
- 它也不能创建对象 ,但是可以被实现 (
implements
,类似于继承,理解继承是亲生的,实现是干的关系) - 一个实现接口的类(可以看做是接口的干儿子类),需要实现接口中所有的抽象方法,创建该干儿子类(实现类)对象,就可以调用方法了,否则它必须是一个抽象类
- 它也不能创建对象 ,但是可以被实现 (
1.2 定义格式
public interface 接口名称 {//跟以前类的写法差不多一致,把class换成interface即可
// 抽象方法1.7之前,方法怎么写都是拿main方法过来修改,m,去掉static
// 默认方法1.8以后
// 静态方法1.8以后
// 私有方法1.9以后
}
1.2.1 含有抽象方法
-
跟抽象类里面的抽象方法用法一致,JDK1.7以前
-
抽象方法:使用
abstract
关键字修饰,可以省略,没有方法体,该方法供子类实现使用
public interface InterFaceName {
public abstract void method(); //抽象方法存在的意义,让子类强制去重写从而实现的事情
void method(); //这种写法跟上面写法一样,public abstract不写,系统给我写,接口独有的
}
1.2.2 含有默认方法和静态方法
-
JDK1.8含以后才有
-
默认方法:使用
default
修饰,不可省略,供子类调用或者子类重写 -
静态方法:使用
static
修饰,供接口名.来直接调用,注意这里不可以给子类调用!!!
public interface InterFaceName {
public default void method() { //default默认,以前类的普通方法加上default
// 执行语句
}
public static void method2() { //跟类的静态方法以前的写法是一样的,接口跟类有点不同,子类不能用
// 执行语句
}
}
1.2.3 含有私有方法和私有静态方法
-
JDK1.9出现,为上面的默认方法和静态方法服务的
-
私有方法:使用
private
修饰,供接口中的默认方法或者静态方法调用
public interface InterFaceName {
private void method() { //私有方法,非静态
// 执行语句
}
private static void method2() { //私有方法,静态
// 执行语句
}
}
1.3 接口的实现
1.3.1 实现的概述
-
类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类
-
实现的动作类似继承,格式相仿,只是关键字不同,实现使用
implements
关键字。 -
非抽象子类实现接口:
- 必须重写接口中所有的抽象方法
- 继承了接口的默认方法,可以直接调用,也可以重写
- 实现格式:
class 类名 implements 接口名 {
// 重写接口中抽象方法【必须】
// 重写接口中默认方法【可选】
}
1.3.2 抽象方法的使用(基本的抽象方法会用就可以了,其他方法目前还是很少用的)
定义接口:
public interface LiveAble {//活着接口
// 定义抽象方法
public abstract void eat();
public abstract void sleep();
}
定义实现类:
public class Animal implements LiveAble {
@Override //alt enter
public void eat() {
System.out.println("吃东西");
}
@Override
public void sleep() {
System.out.println("晚上睡");
}
}
定义测试类:
public class InterfaceDemo {
public static void main(String[] args) {
// 创建子类对象
Animal a = new Animal();
// 调用实现后的方法
a.eat();
a.sleep();
}
}
输出结果:
吃东西
晚上睡
1.3.3 默认方法的使用
- 可以继承,可以重写,二选一,但是只能通过实现类的对象来调用
- 继承默认方法,代码如下:
定义接口:
public interface LiveAble {
public default void fly(){
System.out.println("天上飞");
}
}
定义实现类:
public class Animal implements LiveAble {
// 继承,什么都不用写,直接调用
}
定义测试类:
public class InterfaceDemo {
public static void main(String[] args) {
// 创建子类对象
Animal a = new Animal();
// 调用默认方法
a.fly();
}
}
输出结果:天上飞
- 重写默认方法,代码如下:
定义接口:
public interface LiveAble {
public default void fly(){
System.out.println("天上飞");
}
}
定义实现类:
public class Animal implements LiveAble {
@Override
public void fly() {
System.out.println("自由自在的飞");
}
}
定义测试类:
public class InterfaceDemo {
public static void main(String[] args) {
// 创建子类对象
Animal a = new Animal();
// 调用重写方法
a.fly();
}
}
输出结果:自由自在的飞
1.3.4 静态方法的使用
- 静态与.class 文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用
- 接口静态方法子类无法继承,更加无法重写 代码如下:
定义接口:
public interface LiveAble {
public static void run(){
//接口的静态方法,子类无法继承,更加无法重写
System.out.println("跑起来~~~");
}
}
定义实现类:
public class Animal implements LiveAble {
// 无法重写静态方法
}
定义测试类:
public class InterfaceDemo {
public static void main(String[] args) {
// Animal.run(); // 【错误】无法继承静态方法,不能这样调用,要通过下面的接口名.来调用
LiveAble.run(); //
}
}
输出结果:跑起来~~~
1.3.5 私有方法的使用
-
私有方法:只有默认方法可以调用
-
私有静态方法:默认方法和静态方法都可以调用
如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法去调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助
定义接口:
public interface LiveAble {
default void func(){
func1();
func2();
}
private void func1(){
System.out.println("跑起来~~~");
}
private void func2(){
System.out.println("跑起来33~~~");
}
}
上面抽象方法1.7,默认方法和静态方法1.8,私有方法1.9总的使用代码如下:
public class Test02 {
public static void main(String[] args) {
//Jiekou j = new Jiekou();//接口不能创建对象,所有要有干儿子类,实现类
// Jiekou.method3();//接口静态方法,接口名.调用,子类不能使用
Son s = new Son();
s.method();
s.method2();
}
}
class Son implements Jiekou {//实现继承,干,亲生
//alt enter
@Override
public void method() {
System.out.println("sonmethod");
}
}
interface Jiekou {//default接口才有,类没有
//抽象方法,1.7和以前
// public void method(){};普通方法,修修改改
public abstract void method();//强制要求子类重写
//默认方法和静态方法,1.8
public default void method2(){//子类可以继承(实现),也可以重写,可选的,对象的,后有,后有的可以先有的
method4();
method4();
method5();
}
public static void method3(){//子类不能使用,不能继承也不能重写,子类不能使用,给接口服务,接口名.使用,类,
System.out.println("staticmethod3");
//method4();//报错
method5();
}
//私有方法,给上面默认方法和静态方法服务的,跟子类无关
private void method4(){//私有非静态
System.out.println("defaultmethod2");//100
}
private static void method5(){//私有静态,类,接口,类似,先有类,
System.out.println("staticdefaultmethod2");//100
}
}
1.4 接口的多实现
-
类与接口是实现关系,实现是干的关系,接口是干爹,干爹可以有多个,即类可以实现多个接口,多认多个干爹而已
-
在继承体系中,一个类只能继承(亲生血缘关系)一个父类(亲爹)
-
而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口
实现格式:
class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {
// 重写接口中抽象方法【必须】
// 重写接口中默认方法【不重名时可选】
}
[ ]继承: 表示可选操作
1.4.1 抽象方法
-
接口中,有多个抽象方法时,实现类必须重写所有抽象方法**。*
-
如果抽象方法有重名的,只需要重写一次
定义接口A、B:
interface A {
public abstract void showA();
public abstract void show();
}
interface B {
void showB();
void show();
}
定义实现类:类C实现接口A和B,重写了showA()、showB()及A和B中都有的show()方法
public class C implements A,B{
@Override
public void showA() {
System.out.println("showA");
}
@Override
public void showB() {
System.out.println("showB");
}
@Override
public void show() {
System.out.println("show");
}
}
1.4.2 默认方法
- 接口中,有多个默认方法时,实现类都可继承使用(可继承可不继承使用)
- 如果默认方法有重名的,必须重写一次
定义多个接口:
interface A {
public default void methodA(){}
public default void method(){}
}
interface B {
public default void methodB(){}
ublic default void method(){}
}
定义实现类:
public class C implements A,B{
@Override
public void method() {
System.out.println("method");
}
}
1.4.3 静态方法
接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法
1.4.5 优先级的问题(类继承>实现接口,亲爹>干爹)
- 当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执行父类的成员方法
定义接口:
interface A {
public default void methodA(){
System.out.println("AAAAAAAAAAAA");
}
}
定义父类:
class D {
public void methodA(){
System.out.println("DDDDDDDDDDDD");
}
}
定义子类:
class C extends D implements A {
// 未重写methodA方法
}
定义测试类:
public class Test {
public static void main(String[] args) {
C c = new C();
c.methodA();
}
}
输出结果:DDDDDDDDDDDD
1.5 接口的多继承【了解】
-
接口的出现打破了类单继承的局限性
-
一个接口能继承另一个或者多个接口,这和类之间的继承比较相似
-
接口的继承使用
extends
关键字,子接口继承父接口的方法。**如果父接口中的默认方法有重名的,那么子接口需要重写一次。**代码如下:
定义父接口:类与类是同类血缘关系继承,类与接口不是同类,没有血缘关系干实现,接口与接口是同类,血缘关系继承
interface A {
public default void method(){
System.out.println("AAAAAAAAAAAAAAAAAAA");
}
}
interface B {
public default void method(){
System.out.println("BBBBBBBBBBBBBBBBBBB");
}
}
定义子接口:
interface D extends A,B{
//alt enter,重写实现,快捷键
@Override
public default void method() {
System.out.println("DDDDDDDDDDDDDD");
}
}
小贴士:
子接口重写默认方法时,default关键字可以保留。
子类重写默认方法时,default关键字不可以保留。(接口里面才有default方法,类里面没有,只有switch会出现default关键字)
1.6 其他成员特点//选择题可能考
-
接口中,无法定义成员变量,但是可以定义全局常量,其值不可以改变,默认使用public static final修饰
-
接口中,没有构造方法,接口不是类,凡是类都有构造方法
-
接口中,没有静态代码块