为什么Java 8推出了default methods?
- 在Java1.7的版本里面,接口只允许存在public abstract 方法,或者public static final 变量,不管你是否声明,interface里面的定义的方法,隐含一定是public abstract的
- 同样,每个声明在interface里面的变量,隐含也一定是public static final的,无论你是否明确声明
- 在Java 8的时候,我们可以在interface里面定义一个确切的方法,而不是抽象方法,这个方法需要加上default关键字,称之为default method,比如
default void method1(){
System.out.println("default method1");
}
- 所有实现此接口的类都将继承这个default方法,可以直接使用,也可以覆盖
由上,我们大概可以猜出default method的作用:主要是为了方便向后兼容,扩展已有接口,但是不影响其他的实现类;如果没有默认方法,给某个接口添加一个新的抽象方法,那么所有实现了该接口的类都得修改,影响将会非常大
Default method
- 默认方法的语法很简单就是在interface里面定义一个带有default关键字的方法,就是default method
- default method默认就是可以被所有它的实现类使用,当然如果需要,类里面也可以覆盖这个default method。下面看个简单的例子:
Interface inter {
default void method1(){
System.out.println("default method1");
}
}
Class Demo implements Interf {
public static void main(String[] args) {
Demo demo = new Demo ();
demo.method1();
}
}
- 一个接口继承另外一个接口,同样会继承接口里面的default methods
- 如果两个接口定义同样名字的default method,这个时候一个类同时实现了这两个接口会这么样呢?
Interface interf1{
default void method1(){
System.out.println("default method1 from Interf1");
}
}
Interface interf2{
default void method1(){
System.out.println("default method1 from Interf2");
}
}
class Demo implements interf1, interf2{ // compile error
}
上面的代码,Demo类会报编译错误,要求你去覆盖method1 方法,因为编译器不知道哪个method1方法是你需要的。我们修改下Demo类
Class Demo implements Interf1, interf2 {
@Override
public void method1() {
System.out.println("method1 from Demo");// Or Interf1.super.method1();
}
public static void main(String[] args) {
Demo demo = new Demo ();
demo.method1();
}
}
interface with default methods 不同于 abstract class
即使interface里面可以定义确切的方法,但是还是并不等同于抽象类
带有默认方法的接口 | 抽象类 |
---|---|
接口里面定义的变量永远是public static final的,不能定义instance变量 | 抽象类里面是允许出现instance变量的 |
Interface never talks about state of Object. | Abstract class can talk about state of Object. |
Interface里面不能定义构造方法 | 抽象类里面可以 |
不能定义static,instance block | 抽象类里面可以 |
Default method can refer lambda expression | 抽象类里不可以 |
不能override Object 方法 | 抽象类里可以 |
Java Comparator
比如Java8 里面Comparator接口,通常我们需要sort的时候需要实现Comparator接口, 因为Comparator是一个functional interface,我们可以使用lambda表达式
myDeck.sort(
(firstCard, secondCard) ->
firstCard.getRank().value() - secondCard.getRank().value()
);
那Comparator
实现一个[Comparing
]方法,将会更加方便,如下:
myDeck.sort(Comparator.comparing(Card::getRank));
Comparator
接口还提供了其他的一些方法比如 comparingDouble
和comparingLong
.
假设你想比较对一个cards排序,首先根据它的rank,然后根据他的suit,那么你可能会写成如下的代码:
StandardDeck myDeck = new StandardDeck();
myDeck.shuffle();
myDeck.sort(
(firstCard, secondCard) -> {
int compare =
firstCard.getRank().value() - secondCard.getRank().value();
if (compare != 0)
return compare;
else
return firstCard.getSuit().value() - secondCard.getSuit().value();
}
);
然 Comparator
接口提供了更加方便的方法 thenComparing
:
myDeck.sort(
Comparator
.comparing(Card::getRank)
.thenComparing(Comparator.comparing(Card::getSuit)));
由这个例子我们可以看到,Comparator 接口是如何通过default method来增强它的功能。
参考资料
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
网友评论