对上一篇接口问题的补充说明
我们印象中的接口一直停留在:只能有静态方法和变量。而在实际开发中,这种接口的实现是有利有弊的,优点在于面向抽象而不是面向具体编程,而缺陷就是每次修改接口时,都需修改全部实现了该接口的类。
所以在jdk1.8之后,引入了一个新的关键字default,通过其修饰方法,我们可以在接口中定义方法的具体实现;另外也可以有static修饰的具体方法。
下边将会介绍default关键字,接口的写法,实现方法以及接口新特性
default
default是在Java8之后引入的新关键字,也可以称virtual extension methods,即虚拟扩展方法。也就是可以在接口内部实现一些包含方法体的方法,从而使接口可以在不影响与接口相关实现类代码的同时进行一定的扩展。
接口
- 新式接口的写法可以如下:
public interface Interface{
//抽象方法
public void eat();
//默认方法(可以有多个)
default void defaultMethod(){
System.out.print("这是一个默认方法");
}
//静态方法(可以有多个)
static void staticMethod(){
System.out.print("这是一个静态方法");
}
}
- 实现接口的类
public class People implements Interface{
public static void main(String[] args) {
//默认方法 和 抽象方法需实现类实例化后调用
People p = new People();
//抽象方法重写后调用
p.eat();
//默认方法重写后调用
p.defaultMethod();
//静态方法直接通过接口调用
Interface.staticMethod();
}
//抽象方法
public void eat(){
System.out.println("这是一个抽象方法的具体实现");
}
//默认方法(可以有多个)
public void defaultMethod(){
System.out.println("重写默认方法");
Interface.super.defaultMethod();
}
//静态方法不可被重写
//执行结果
这是一个抽象方法的具体实现
重写默认方法
这是一个默认方法
这是一个静态方法
}
- 补充:函数式接口:只含有一个抽象方法的接口就是函数式接口,为了支持lambda表达式。
接口新特性
- 静态方法可以直接被接口调用,但不能被重写
Interface.staticMethod();
由图可见,能够被重写的方法只有抽象方法和默认方法
- 继承一个接口
public interface Interface{
default void defaultMethod(){
System.out.print("这是一个默认方法");
}
}
//实现类A
public class People implements Interface{
public static void main(String[] args) {
People p = new People();
//直接调用默认方法
p.defaultMethod();
}
}
- 当一个类同时继承两个接口A,B,且A,B中存在方法同名,就需在类中重写方法
//接口1
public interface Interface{
default void defaultMethod(){
System.out.print("这是一个默认方法");
}
}
//接口2
public interface Interface2{
default void defaultMethod(){
System.out.print("这是一个默认方法2");
}
}
//让类A同时实现接口1和接口2
public class People implements Interface,Interface2{
public static void main(String[] args) {
People p = new People();
//默认方法重写后调用
p.defaultMethod();
}
//重写默认方法(根据自己实际的业务需要重写即可)
public void defaultMethod(){
System.out.println("重写默认方法");
}
}
- 当一个类同时继承一个类A又实现一个接口B时,且AB中含有同名方法,则类优先于接口
//接口
public interface Interface{
default void defaultMethod(){
System.out.print("这是接口中的方法");
}
}
//父类
public class father{
public void defaultMethod(){
System.out.print("这是类中的方法");
}
}
//实现类A
public class People extends father implements Interface{
public static void main(String[] args) {
People p = new People();
//直接调用默认方法
System.out.print(p.defaultMethod());
}
}
//输出
这是类中的方法
- 接口可以作为参数使用
将类当成参数传入方法,其实就是将类的对象传入方法,如果是抽象类,其实就是将抽象类的子类的对象传入方法,如果是接口,其实就是将接口实现类的对象传入方法。
public interface Interface{
public void eat();
}
//实现类A
public class A implements Interface{
public static void main(String[] args) {
People p = new People();
//直接调用默认方法
p.method(p);//由此可见实际传入的就是接口的实现类
}
//定义一个参数为接口的方法
public void method(Interface in){
in.eat();
}
//重写抽象方法
public void eat(){
System.out.println("这是一个抽象方法的具体实现");
}
}
//输出
这是一个抽象方法的具体实现