五 接口
部分子类共同存在的方法(不是所有子类、不知单独一个子类)
接口:就是一种规则
接口和抽象类的异同:
接口就是一种规则,是对行为的抽象
5.1 接口的定义、使用
接口用关键字
interface来定义
public interface 接口名{}接口不能实例化(不能直接创建对象)
接口和类之间是实现关系,通过
implements关键字表示
public class 类名 implements 接口名 {}接口的子类(实现类)
要么重写接口中的所有抽象方法
要么是抽象类
注意:
// 1.接口和类的实现关系,可以单实现,也可以多实现
public class 类名 implements 接口名1, 接口名2{}
// 2.实现类还可以在继承一个父类的同时,实现多个接口
public class 类名 extends 父类 implements 接口名1, 接口名2 {}5.2 基础练习
编写带有接口和抽象类的标准 javabean 类
青蛙 属性:名字、年龄 行为:吃虫子、蛙泳
狗 属性:名字、年龄 行为:吃骨头、狗刨
兔子 属性:名字、年龄 行为:吃胡萝卜实现代码:
//Animal.jaav
public abstract class Animal {
private String name;
private int age;
public Animal() {}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
public abstract void eat();
}
//Frog.java
public class Frog extends Animal implements Swim{
public Frog() {}
public Frog(String name, int age) {super(name, age);}
@Override
public void eat() {System.out.println("青蛙在吃虫子");}
@Override
public void swim() {System.out.println("青蛙在蛙泳");}
}
//Dog.java
public class Dog extends Animal implements Swim{
public Dog() {}
public Dog(String name, int age) {super(name, age);}
@Override
public void eat() {System.out.println("狗在吃骨头");}
@Override
public void swim() {System.out.println("狗刨");}
}
//Rabbit.java
public class Rabbit extends Animal {
public Rabbit() {}
public Rabbit(String name, int age) {super(name, age);}
@Override
public void eat() {System.out.println("兔子在吃胡萝卜");}
}
//Swim.java
public interface Swim {
public abstract void swim();
}
//Test.java
public class Test {
public static void main(String[] args) {
//创建青蛙的对象
Frog f = new Frog("小青蛙", 1);
System.out.println(f.getName() + ", " + f.getAge());
f.eat();
f.swim();
//创建兔子的对象
Rabbit r = new Rabbit("小白", 2);
System.out.println(r.getName() + ", " + r.getAge());
r.eat();
}
}
5.3 接口中成员的特点
5.3.1 成员变量
只能是常量
默认修饰符:
publicstaticfinal
5.3.2 构造方法(没有)
接口中没有构造方法
5.3.3 成员方法
只能是抽象方法
默认修饰符:public abstract
JDK7以前:接口中只能定义抽象方法
JDK8新特性:接口中可以定义有方法体的方法
JDK9新特性:接口中可以定义私有方法
示例代码:
//Inter.java
public interface Inter {
//public static final int a = 10;
int a = 10;
//public abstract void method();
void method();
}
//InterImpl.java
public class InterImpl implements Inter{
@Override
public void method() {System.out.println("method");}
}
//Test.java
public class Test {
public static void main(String[] args) {
System.out.println(Inter.a);
//Inter.a = 20; //Cannot assign a value to final variable 'a'
//创建实现类对象。并调用方法
InterImpl ii = new InterImpl();
ii.method();
Scanner sc = new Scanner(System.in);
sc.next();
}
}5.4 接口和类之间的关系
5.4.1 类和类的关系
继承关系
只能单继承,不能多继承
但是可以多层继承
5.4.2 类和接口的关系
实现关系
可以单实现,也可以多实现
还可以在继承一个类的同时实现多个接口
示例1:(一个类中实现多个接口,需要重写接口中所有的方法)
//Inter1.java
public interface Inter1 {
public abstract void method1();
public abstract void method2();
public abstract void method3();
}
//Inter2.java
public interface Inter2 {
public abstract void method4();
public abstract void method5();
public abstract void method6();
}
//InterImpl.java
public class InterImpl implements Inter1, Inter2{
@Override
public void method1() {System.out.println("method1");}
@Override
public void method2() {System.out.println("method2");}
@Override
public void method3() {System.out.println("method3");}
@Override
public void method4() {System.out.println("method4");}
@Override
public void method5() {System.out.println("method5");}
@Override
public void method6() {System.out.println("method6");}
}
//Test.java
public class Test {
public static void main(String[] args) {
InterImpl ii = new InterImpl();
ii.method1();
ii.method2();
ii.method3();
ii.method4();
ii.method5();
ii.method6();
}
}示例2:(一个类中实现多个接口,不同接口中有重名方法,重名的方法重写一次即可)
//Inter1.java
public interface Inter1 {
public abstract void method1();
public abstract void method2();
public abstract void method3();
}
//Inter2.java
public interface Inter2 {
public abstract void method1();
public abstract void method2();
public abstract void method3();
public abstract void method4();
}
//InterImpl.java
public class InterImpl implements Inter1, Inter2{
@Override
public void method1() {System.out.println("method1");}
@Override
public void method2() {System.out.println("method2");}
@Override
public void method3() {System.out.println("method3");}
@Override
public void method4() {System.out.println("method4");}
}
//Test.java
public class Test {
public static void main(String[] args) {
InterImpl ii = new InterImpl();
ii.method1();
ii.method2();
ii.method3();
ii.method4();
}
}5.4.3 接口和接口的关系
继承关系
可以单继承,也可以多继承
注意:如果实现类实现了最下面的子接口,那么就需要重写所有的抽象方法
示例代码:
Inter3 继承于Inter1 和 Inter2 ,实现类(InterImpl) 实现了 Inter3 接口,那么 InterImpl 需要重写所有的抽象方法
//Inter1.java
public interface Inter1 {
public abstract void method1();
}
//Inter2.java
public interface Inter2 {
public abstract void mehtod2();
}
//Inter3.java
public interface Inter3 extends Inter1,Inter2{
public abstract void method3();
}
//InterImpl.java
public class InterImpl implements Inter3{
@Override
public void method1() {System.out.println("method1");}
@Override
public void mehtod2() {System.out.println("method2");}
@Override
public void method3() {System.out.println("method3");}
}
//Test.java
public class Test {
public static void main(String[] args) {
//接口、接口之间是继承关系;可以单继承,也可以多继承
//细节:如果实现类实现了最下面的子接口,那么就需要重写所偶遇的抽象方法
InterImpl ii = new InterImpl();
ii.method1();
ii.mehtod2();
ii.method3();
}
}5.5 拓展练习
现在有乒乓球运动员、篮球运动员,乒乓球教练、篮球教练
为了出国交流,跟乒乓球相关的人员都需要学习英语
在这个案例中,哪些是具体类,哪些是抽象类,哪些是接口?
乒乓球运动员:姓名、年龄、学打乒乓球、说英语
篮球运动员:姓名、年龄、学打篮球
乒乓球教练:姓名、年龄、教打乒乓球、说英语
篮球教练:姓名、年龄、教打篮球
实现代码:
功能类
//Person.java
//不想让外界直接创建人的对象,直接创建人的对象没有意义,所以将其写为抽象类
public abstract class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
//Sporter.java
public abstract class Sporter extends Person{
public Sporter(String name, int age) {super(name, age);}
public Sporter() {}
public abstract void study();
}
//Coach.java
public abstract class Coach extends Person{
public Coach(String name, int age) {super(name, age);}
public Coach() {}
public abstract void teach();
}
//PingPangSporter.java
public class PingPangSporter extends Sporter implements English{
public PingPangSporter(String name, int age) {super(name, age);}
public PingPangSporter() {}
@Override
public void speakEnglish() {System.out.println("乒乓球运动员在说英语");}
@Override
public void study() {System.out.println("乒乓球运动员在学习打乒乓球");}
}
//PingPangCoach.java
public class PingPangCoach extends Coach implements English{
public PingPangCoach(String name, int age) {super(name, age);}
public PingPangCoach() {}
@Override
public void teach() {System.out.println("乒乓球教练正在教如何打乒乓球");}
@Override
public void speakEnglish() {System.out.println("乒乓球教练正在学习说英语");}
}
//BasketballSporter.java
public class BasketballSporter extends Sporter{
public BasketballSporter(String name, int age) {super(name, age);}
public BasketballSporter() {}
@Override
public void study() {System.out.println("篮球运动员在学习如何打篮球");}
}
//BasketballCoach.java
public class BasketballCoach extends Coach{
public BasketballCoach(String name, int age) {super(name, age);}
public BasketballCoach() {}
@Override
public void teach() {System.out.println("狼求教练正在教如何打篮球");}
}
//English.java
public interface English {
public abstract void speakEnglish();
}测试类
//Test.java
public class Test {
public static void main(String[] args) {
//创建对象
PingPangSporter pps = new PingPangSporter("张三", 23);
System.out.println(pps.getName() + ", " + pps.getAge());
pps.study();
pps.speakEnglish();
PingPangCoach ppc = new PingPangCoach("lisi", 24);
System.out.println(ppc.getName() + ", " + ppc.getAge());
ppc.teach();
ppc.speakEnglish();
BasketballSporter bbs = new BasketballSporter("wangwu", 25);
System.out.println(bbs.getName() + ", " + bbs.getAge());
bbs.study();
BasketballCoach bbc = new BasketballCoach("zhaoliu", 26);
System.out.println(bbc.getName() + ", " + bbc.getAge());
bbc.teach();
}
}5.6 JDK8开始接口中新增的方法
接口升级时,处理兼容问题(升级后,之前用接口的类不需要重写方法)
JDK7以前:接口中执行能定义抽象方法
JDK8的新特性:接口中可以定义有方法体的方法(默认、静态)
JDK9的新特性:接口中可以定义私有方法
5.6.1 接口中定义默认方法
允许在接口中定义默认方法,需要使用关键字
default修饰作用:解决接口升级的问题
接口中默认的定义格式
//格式
public default 返回值类型 方法名(参数列表){}
//示例
public default void show(){}接口中默认方法的注意事项:
1、默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写的时候去掉 default 关键字
示例代码:
//Inter.java
public interface Inter {
public abstract void method();
//默认方法(show)不是抽象方法,所以不会强制被重写
public default void show() {
System.out.println("接口中的默认方法 --- show");
}
}
//InterImpl.java
public class InterImpl implements Inter{
@Override //
public void method() {
System.out.println("实现类重写的抽象方法 --- method");
}
//默认不会被强制重写,如果被重写,重写的时候去掉 `default` 关键字
@Override
public void show() {
System.out.println("重写接口中的默认方法 --- show");
}
}
//Test.java
public class Test {
public static void main(String[] args) {
InterImpl ii = new InterImpl();
ii.method();
ii.show();
}
}2、public 可以省略,default 不能省略
public interface Inter {
//public可以省略
public abstract void method();
//default不能省略
public default void show() {
System.out.println("接口中的默认方法 --- show");
}
}3、如果实现多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
//InterA.java
public interface InterA {
public default void show() {
System.out.println("InterA接口中的默认方法 --- show");
}
}
//InterB.java
public interface InterB {
public default void show(){
System.out.println("InterB接口中的默认方法 --- show");
}
}
//InterImpl.java
public class InterImpl implements InterA,InterB {
//InterImpl类实现InterA、InterB接口,两个接口中存在相同名字的默认方法(show),则必须要重写show方法
@Override
public void show() {
System.out.println("重写接口中的默认方法 --- show");
}
}
//Test.java
public class Test {
public static void main(String[] args) {
InterImpl ii = new InterImpl();
ii.show();
}
}5.6.2 接口中定义静态方法
允许在接口中定义静态方法,需要用
static修饰
接口中静态方法的定义格式
//格式
public static 返回值类型 方法名(参数列表){}
//示例
public static void show(){}注意事项:
1、静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
2、public 可以省略,static 不能省略
//Inter.java
public interface Inter {
public abstract void method();
// `public` 可以省略,`static` 不能省略
public static void show(){
System.out.println("Inter接口中的静态方法");
}
}
//InterImpl.java
public class InterImpl implements Inter{
@Override
public void method() {
System.out.println("InterImpl重写的抽象方法");
}
//不叫重写
public static void show(){
System.out.println("InterImpl定义的重名show方法");
}
}
//Test.java
public class Test {
public static void main(String[] args) {
//调用接口中的静态方法
Inter.show();
//调用实现类中的静态方法
InterImpl.show();
}
}5.6.3 接口中定义私有方法
接口中私有方法的定义格式
//格式1
private 返回值类型 方法名(参数列表){}
//示例1
private void show(){}
//格式2
private static 返回值类型 方法名(参数列表){}
//示例2
private static void method(){}示例代码:
package com.yq.a10interfacedemo8;
public interface InterA {
public default void show1(){
System.out.println("show1方法开始执行");
show3();
}
public default void show2(){
System.out.println("show2方法开始执行");
show3();
}
public static void show5(){
show4();
}
public static void show6(){
show4();
}
//普通的私有方法,给默认的方法服务的
private void show3(){
System.out.println("记录程序在运行过程中的各种细节,这里有100行代码");
}
//静态的私有方法,给静态方法服务的
private static void show4(){
System.out.println("记录程序在运行过程中的各种细节,这里有100行代码");
}
}5.7 接口的应用
1、接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这个类实现对应的接口即可
2、当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态
5.8 适配器设计模式
设计模式:一套被反复使用、多数人知晓、经过分类编目、代码设计经验的总结
解决各种问题的套路
适配器设计模式:解决接口与接口实现类之间的矛盾问题
实现步骤:
1.编写中间类XXXAdapter,实现对接的接口
2.对接口中的抽象方法进行空实现
3.让真正实现类继承中间类,并重写需要用到的方法
4.为了避免其他类创建适配器类(XXXAdapter)的对象,中间的适配器类用abstract进行修饰注意:若最后的实现类需要继承其他类时,可以让中间类继承父类,再让最后的实现类继承中间类
示例代码:
//Inter.java
public interface Inter {
public abstract void method1();
public abstract void method2();
public abstract void method3();
public abstract void method4();
public abstract void method5();
public abstract void method6();
public abstract void method7();
public abstract void method8();
public abstract void method9();
public abstract void method10();
}
//InterAdapter.jaa
package com.yq.a11interfacedemo9;
//abstract让InterAdapter变成抽象类(不让外界直接创建对象)
public abstract class InterAdapter implements Inter{
@Override
public void method1() {}
@Override
public void method2() {}
@Override
public void method3() {}
@Override
public void method4() {}
@Override
public void method5() {}
@Override
public void method6() {}
@Override
public void method7() {}
@Override
public void method8() {}
@Override
public void method9() {}
@Override
public void method10() {}
}
//InterImpl.java
public class InterImpl extends InterAdapter{
//需要用到哪个方法,重写哪个方法即可
@Override
public void method5() {
System.out.println("只需要用到第五个方法");
}
}
评论区