avatar

java8新特性 —— 默认方法

在Java8没有发布之前,如果我们要改动一个接口增加一个方法需要2个步骤:

  1. 在接口中增加方法
  2. 修改每一个接口实现,实现该方法

使用新特性就只需要在接口中使用 default 定义方法,所有实现类的实例都可以调用该方法。不用每个实现类都实现方法了,方便太多了。

默认方法

  • 用 default 关键字来定义,必须有方法体。
  • 可以被重写、可以被重栽
  • 当有多个相同的默认方法时需要根据规则来选择使用哪一个

如果一个类使用相同的函数签名从多个地方(比如另一个类或接口)继承了方法,通过三条规则可以进行判断。
1. 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。
2. 如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。
3. 最后,如果还是无法判断,继承了多个接口的类必须通过显式覆盖和调用期望的方法,显式地选择使用哪一个默认方法的实现


​ 我们在定义接口的时候可以考虑,有些方法是不是每个实现类中的实现都完全相同的,如果有完全相同的,我们可以考虑直接在接口中定义成默认方法。定义默认方法用 default来修饰,这个默认方法和其他的不太一样,它有方法体。下面我们举例来说明,比较直观。这里我们用动物(Animal) 来举例说明,
动物都有发出声音、吃、行走等一些属性动作,吃、行动物都有相同的,但是叫声不同,定义成接口,我们可以这样来定义:

1
2
3
4
5
6
7
8
9
10
public interface IAnimal {
void greet ();
default void eat () {
System.out.println("吃...");
}
default void move () {
System.out.println("行走...");
}

}

将吃、移动定义成默认方法,并且写上默认的实现逻辑。我们再定义一个实现,用小狗(Dog) 来实现动物的相关属性方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Dog implements IAnimal{
@Override
public void greet() {
System.out.println("汪汪...");
}

public static void main(String[] args) {
Dog dog = new Dog();
dog.greet();
dog.eat();
dog.move();
}
}

这里看到,实现类中并没有实现 eat()、move() 这两个方法,但是我们在实例中一样可以访问这些默认的方法。

如果我们要更改默认方法的实现,可以重写接口中的默认方法来达到目的。

Java是单继承,但是可以实现多个接口,这里我们来试一下看多个接口中定义相同的默认方法,看是什么效果,话不多说,直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public interface IAnimal1 {
default void eat () {
System.out.println("eat...");
}
default void sleep () {
System.out.println("睡觉...");
}
}

public class Dog implements IAnimal, IAnimal1{
@Override
public void greet() {
System.out.println("汪汪...");
}

public static void main(String[] args) {
Dog dog = new Dog();
dog.greet();
dog.eat();
dog.move();
}
}

IAnimalIAnimal1 这两个接口中都定义了eat这个默认方法,发现直接编译报错:

1
com.shl.java8.Dog inherits unrelated defaults for eat() from types com.shl.java8.IAnimal and com.shl.java8.IAnimal1

提示有2个 eat默认方法,不知道用哪一个了。存在相同的默认方法,我们来根据冲突规则来对照,发现规则1、2都不能满足,这个时候我们就要在实现类中显式的指定eat 这个方法,就可以正常的调用了。

1
2
3
4
5
6
7
8
9
10
11
public class Dog implements IAnimal, IAnimal1{
@Override
public void greet() {
System.out.println("汪汪...");
}

@Override
public void eat() {
System.out.println("吃...");
}
}
文章作者: 惆怅客
文章链接: https://www.songhailong.com/articles/9d7d3e20/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 惆怅客

评论