Java8为什么要提供默认方法呢?
答案是为了向后兼容。因为向已经发布的接口添加新的方法,一旦接口发生了变化,接口的实现者都需要更新代码,这样工作量就很大。为了解决这个问题,Java8就提供了默认方法。
默认方法前边用 default 关键字修饰。
- 示例
public interface DefaultMethod {
/**
* 普通方法,只定义,不实现
*/
void odlFun();
/**
* 默认方法,又定义,又实现
*/
default void newFun() {
}
}
- 那么默认方法和抽象类有什么区别呢? (其实是接口和抽象类的区别)
* 相同点:
* 1.都是抽象类型
* 2.都可以有实现方法 (以前不行,现在接口可以有默认方法)
* 3.都可以不需要实现类或者继承者实现所有方法(以前不行,现在接口中的默认方法可以不需要实现者实现)
*
* 不同点:
* 1.一个类只能继承一个抽象类,但是接口可以多继承
* 2.接口中定义的变量都是public static final修饰的,且必须给其初始值,所以实现类中不能修改其值。
* 正是因为如此,接口中是没有实例变量的,只有类变量或者叫静态变量。
正是因为Java8接口提供了默认方法,所以,侧面我们也可以理解为Java以一种特别的形式实现了多继承。
那么默认方法都有哪些使用场景呢?
- 默认方法的使用场景:
1.可选方法 为接口提供可选的方法,给出默认实现,这样实现类就不用显示的去提供一个空的方法
2.实现多继承 继承是面向对象的特性之一,在Java中一直以来都是单继承的原则,
Java8中默认方法为实现多继承提供了可能。
那么既然接口存在多实现,就有可能存在默认方法冲突的问题。
假如class C 实现了接口A和接口B,接口A和接口B都有一个同名的默认方法test,那么这种情况下肯定是存在默认方法冲突的问题的。
首先,我们先来了解一些知识点,了解了这些知识点,我们很容易就能解决这种冲突问题。
1.类中的方法优先级最高。如果类和父类(抽象类也OK)中声明了相同签名的方法,那么类中的优先级最高。
2.如果第一条无法确定,那么最具体的的实现的默认方法;
很绕,举例子:B接口继承了A,B就更加具体,那么B中的方法优先级最高
3.如果上面两个都无法判断,那么编译会报错,需要在实现接口,然后手动显式调用
public interface A {
default void test() {
System.out.println("默认方法A");
}
}
public interface B {
default void test() {
System.out.println("默认方法B");
}
}
public class C implements A, B {
@Override
public void test() {
A.super.test();
}
@Test
public void test2() {
test();
}
}
- 小结
- 默认方法由default修饰
- 默认方法使用的场景是可选方法和多继承
- 利用三个原则解决方法名相同的默认方法冲突的问题