先谈一谈抽象类和接口的区别
抽象类
可看做是不可实例化的普通类,可以拥有构造方法,可以有main方法
抽象类中的方法可以是抽象方法(抽象方法必须存在于抽象类中),也可以是普通方法、静态方法
可以声明变量,不是必须赋初值。
抽象类可以继承其它类,也可实现接口
抽象类的派生类,必须覆盖父类中abstract修饰的所有方法
接口
接口仅可继承其他接口,不可继承其它类或实现另外的接口
接口中的方法默认为abstract类型
接口中声明的变量必须赋初值,且不可再改变,因为所有变量都是static final类型的
对于JDK7及以前版本:
1. 接口中的方法不可有方法体(因为默认是抽象方法),不可有静态方法。
2. 接口的实现类,必须实现接口中的所有方法(包括接口本身的和从其它接口继承的)
对于JDK8及以后版本:
1. 接口中default方法可有方法体,也可在接口里写静态方法。
2. 接口的实现类,必须实现接口中除default类型的其它所有方法(包括接口本身的和从其它接口继承的)
再说说default关键字:
自Java8加入
用来修饰方法,使得在接口中的方法可以写入方法体
接口的实现类若没有实现(也可以叫覆盖)default类型的方法,则可在实现类中直接调用(接口says:你不覆盖,那就按这个默认的来了啊)。否则,是正常的覆盖,实现多态。
个人理解:
1. default的加入,使得我们在接口类中增加方法时,不必一个个地改动实现类了(添加一个default方法时,实现类可以不去管),使得接口和抽象类更为贴近了一步。
2. 很多的抽象类可以被精简掉了,实现接口的抽象类中写的方法体代码可以直接移到接口中,派生类直接实现接口即可,具体可以看WebMvcConfigurerAdapter被废弃的例子
附上一个实验例子,两个接口是继承关系,一个类来实现其中一个接口,实验各种调用:
interface BaseRadio {
void sent(String a,String b);
int port = 9800;
default void close() {
System.out.println(port);
System.out.println("关了");
}
static void prt(){
System.out.println("uvb77");
}
default void open() {
System.out.println("打开");
}
}
interface Radio extends BaseRadio {
void sent();
void sent(int s);
int sent(String a);
@Override
default void close() {
System.out.println(port + 1);
System.out.println("我是Radio重写的");
}
static void prt(){
System.out.println("uvb76");
}
}
public class TestRadio implements Radio {
@Override
public void sent() {
System.out.println("我是BaseRadio里的");
}
@Override
public void sent(int s) {
System.out.println("我是BaseRadio里的");
}
@Override
public int sent(String a) {
System.out.println("我是BaseRadio里的");
return 0;
}
@Override
public void sent(String a, String b) {
System.out.println("我是Radio里的!!!!!");
}
@Override
public void close() {
System.out.println(port + 2);
System.out.println("我是TestRadio重写的");
}
public static void main(String[] args) {
TestRadio testRadio = new TestRadio();
System.out.println("调用实现类覆盖的default方法,经过了2次覆盖,已经和原来完全不同了:");
testRadio.close();
System.out.println("实现类调用BaseRadio接口的default方法,就好像自己的方法哦:");
testRadio.open();
System.out.println("打印接口里声明的port:" + TestRadio.port);
Radio.prt();
System.out.println("调用接口的静态方法");
BaseRadio.prt();
}
}
最终输出如下:
调用实现类覆盖的default方法,经过了2次覆盖,已经和原来完全不同了:
9802
我是TestRadio重写的
实现类调用BaseRadio接口的default方法,就好像自己的方法哦:
打开
打印接口里声明的port:9800
uvb76
调用接口的静态方法
uvb77