通过之前对 JAVA基础 —— 面向对象 以及 JAVA基础 —— 面向对象内存图 的学习。
接下来我们将会进一步学习面向对象进阶的相关知识点。
static | JAVA基础 (面向对象进阶)—— Static |
继承 | JAVA基础 (面向对象进阶)—— 继承 |
多态 | JAVA基础 (面向对象进阶)—— 多态 |
包、final、权限修饰符、代码块、抽象类和抽象方法方法 | JAVA基础(面向对象进阶) —— 包、final、权限修饰符、代码块、抽象类和抽象方法方法 |
接口 | JAVA基础 (面向对象进阶)—— 接口 |
内部类 | JAVA基础 (面向对象进阶)—— 内部类 |
目录
一、概念引入
二、接口的定义和使用
三、 接口中成员的特点
四、 接口和类之间的关系
1. 类与类之间
2. 类与接口之间
3. 接口与接口之间
五、接口中新增方法
1. JDK8以后接口中新增的默认方法
2. JDK8以后接口中新增的静态方法
3. JDK9新增的私有方法
六、 适配器设计模式
接口其实就是一种规则,是对行为的抽象。
- 接口用关键字interface来定义:
public interface 接口名 { }
- 接口不能实例化(接口不能创建对象)
- 接口和类之间是实现关系,通过implements关键字表示:
public class 类名 implements 接口名 { }
- 接口的子类(实现类):要么重写接口中的所有抽象方法 ; 要么是抽象类
注意1: 接口和类的实现关系,可以单实现,也可以多实现。
public class 类名 implements 接口名1,接口名2 {}
注意2:实现类还可以在继承一个类的同时实现多个接口。
public class 类名 extends 父名 implements 接口名1,接口名2 {}
练习: 编写带有接口和抽象类的标准Javabean类
动物 属性 行为 青蛙 名字,年龄 吃虫子,蛙泳 狗 名字,年龄 吃骨头,狗刨 兔子 名字,年龄 吃胡萝卜
// 动物类 Animal.java
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();
// 游泳不能写在父类当中
// 写在父类当中就说明子类都会游泳
// public abstract void swim();
}
//Swim接口
public interface Swim {
//游泳接口
public abstract void swim();
}
//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("青蛙在蛙泳");
}
}
//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("兔子在吃胡萝卜");
}
}
//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("狗在狗刨");
}
}
//测试类
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("小兔子",1);
System.out.println(r.getName() + "," + r.getAge());
r.eat();
//r.swim();
}
}
成员变量 | 只能是常量 默认修饰符:public static final |
构造方法 | 没有 |
成员方法 | 只能是抽象方法 默认修饰符:public abstract |
- JDK7以前:接口类只能定义抽象方法。
- JDK8的新特性:接口中可以定义有方法体的方法。
- JDK9的新特性:接口中可以定义私有方法。
继承关系,只能单继承,不能多继承,但是可以多层继承。
- 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口。
- 两个接口中有同名方法只需要重写一次。
//接口1 Inter1
public interface Inter1{
publc abstract void method1();
publc abstract void method2();
publc abstract void method3();
}
//接口2 Inter2
public interface Inter2{
publc abstract void method1();
publc abstract void method2();
publc abstract void method3();
publc abstract void method4();
}
实现类 重写方法:
//实现类 InerImpl.java
pubic class InerImpl 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 ");
}
}
- 继承关系,可以单继承,也可以多继承。
- 实现类实现的是最下面子接口,需要重写所有的抽象方法。
//接口1 Inter1
public interface Inter1{
public abstract void method1();
}
//接口2 Inter2
public interface Inter2{
public abstract void method2();
}
//接口3 Inter3
public interface Inter3 extends Inter1,Inter2{
public abstract void method3();
}
//实现类 InerImpl.java
pubic class InerImpl implements Inter3{
@Override
public void method1(){
System.out.println(" method1 ");
}
@Override
public void method2(){
System.out.println(" method2 ");
}
@Override
public void method3(){
System.out.println(" method3 ");
}
}
JDK7以前设计好的接口后续再添加新的方法规则,那之前写好的实现类就会报错。因此之前接口发生变化,所有的实现类也就不得不随之发生变化。
所以如果在接口里面的方法可以有方法体就可以解决问题了。
- 允许在接口中定义默认方法,需要使用关键字default修饰
作用: 解决接口升级的问题
接口中默认方法的定义格式:
- 格式: public default 返回值类型 方法名 (参数列表) { }
- 范例:public default void show (){ }
接口中默认方法的注意事项:
- 默认方法不是抽象方法,所以不强制被重写。但如果被重写,重写的时候去掉default关键字。
- public可以省略,但default不能省略
- 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写。
//InterA 接口A
public interface InterA {
//默认方法不是抽象方法,所以不强制被重写。
//但如果被重写,重写的时候去掉default关键字。
//抽象方法
public abstract void method ();
//默认方法
//public 可省略 ,但是default 不能
public default void show() {
System.out.println("InterA接口默认方法 --- show");
}
}
//InterB 接口B
public interface InterB {
//默认方法
public default void show() {
System.out.println("InterB接口默认方法 --- show");
}
}
//方法类
public class InterImpl implements InterA, InterB {
@Override
public void method() {
System.out.println("实现类重写的抽象方法");
}
// 省略 会报错
// 不知道调用interA中还是interB中show方法
// 所以会自动强制重写
@Override
// 不能强行书写default 否则会报错
public void show() {
System.out.println("重写接口中的默认方法");
}
}
//实现类
public class Test {
public static void main(String[] args) {
//创建实现类的对象
InterImpl ii = new InterImpl();
ii.method(); //实现类重写的抽象方法
ii.show(); //接口默认方法 --- show
}
}
- 允许在接口中定义定义静态方法,需要用static修饰
接口中静态方法的定义格式:
- 格式: public static 返回值类型 方法名 (参数列表) { }
- 范例: public static void show() { }
接口中静态方法的注意事项:
- 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
- public可以省略,static不能省略
接口中私有方法的定义格式:
- 格式1: private 返回值类型 方法名 (参数列表) { }
- 范例|: private void show(){ }
- 格式2: private static 返回值类型 方法名 (参数列表) { }
- 范例2: private static void method () { }
1.当一个接口中抽象方法过多,但是我们只要使用其中一部分的
时候,就可以适配器设计模式
2.书写步骤:
编写中间类XXXAdapter ,实现对应的接口对接口中的抽象方法进行空实现
让真正的实现类继承中间类,并重写需要用的方法为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰