Java8特性之接口方法
保留所有版权,请引用而不是转载本文(原文地址 https://yeecode.top/blog/12/ )。
1 概述
Java 8由Oracle公司于2014年3月18日发布,至今已过去数年之久。然而,直到今日仍有许多软件开发者对其相关特性不了解,这可能主要是Java教材更新缓慢的原因。为了使大家对与Java8的特性有全面系统的了解,本公众号将连续几篇文章介绍Java8中的各个特性。
Java8中新增的特性主要有:
- Lambda 表达式 − Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。
- 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
- 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
- 新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
- Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
- Date Time API − 加强对日期与时间的处理。
- Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
- Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。
本文介绍其中的默认方法。其它特性会在后续文章中陆续介绍。
2 接口中含有方法实现
早期的Java版本的接口拥有非常的严格的接口,接口中只能有抽象方法,不能存在实现。抽象方法和实现方法混合的,那叫作抽象类。
而继承了接口的对象,必须要指定接口的实现。
2.1 默认方法
而Java8的新特性:接口中也可以有方法的默认实现。集成了接口的对象可以不指定默认方法的实现,而直接使用其默认实现。
我们展开讲一下:
public class TestBean {
public static void main(String[] args) {
Say say = new Say() {
@Override
public void sayHi(String name) {
System.out.println("hei hei");
}
};
say.sayHi("lilei");
say.sayHelloWorld();
}
public interface Say {
void sayHi(String name);
default void sayHelloWorld() {
System.out.println("hello world");
}
}
}
首先我们看一下Say接口,它本身有两个方法,一个抽象方法sayHi(String name),另外一个是带有默认实现的sayHelloWorld()。它本身有default关键字声明,然后可以写它默认的实现。
我们创建了一个匿名对象,必须给抽象方法指定实现,但是默认实现不需要指定,这样就会采用默认的实现方式。
这方面好的例子是大量的方法被添加到java.util.Collection接口中去:stream(),parallelStream(),forEach(),removeIf(),……
尽管默认方法非常强大,但是在使用默认方法时我们需要小心注意一个地方:在声明一个默认方法前,请仔细思考是不是真的有必要使用默认方法,因为默认方法会带给程序歧义,并且在复杂的继承体系中容易产生编译错误。
2.2 静态方法
Java 8带来的另一个有趣的特性是接口可以声明(并且可以提供实现)静态方法。
类似于类中的静态方法,接口定义的静态方法可以独立于任何对象调用。所以,在调用静态方法时,不需要实现接口,也不需要接口的实例,也就是说和调用类的静态方法的方式类似 : Interface.staticFun()
举例子,先定义一个接口:
public interface UserInterface {
static void staticSayHi() {
System.out.println("Hi, static function in interface.");
}
default void defaultSayHi() {
System.out.println("Hi, default function in interface");
}
void normalSayHi();
}
然后定义一个对象:
public class UserBean implements UserInterface{
@Override
public void normalSayHi() {
System.out.println("Hi, normal say hi!");
}
}
调用如下:
public class TestBean {
public static void main(String[] args) {
UserBean userBean = new UserBean();
userBean.normalSayHi(); // 只能用对象userBean访问
userBean.defaultSayHi(); // 只能用对象userBean访问
// staticSayHi作为接口的静态方法,无法使用UserBean类或者userBean对象引用到
// userBean.staticSayHi(); // 错误,调用不到
// 需要使用接口引用
UserInterface.staticSayHi(); // 只能用接口访问
}
}
因此,接口的静态方法只能由接口来调用,它不属于实现了那个接口的对象,对象调用不到。
这时,我们想起了类的静态方法,那它也属于类,但是类的对象能调用到,但是IDEA会直接爆出警告,因此,虽然能调用到,但是极为不推荐。
3 总结
Java8 提供的接口中的默认方法为编程的灵活性注入了新活力。接口默认方法使得我们不必强制实现接口中的所有方法,能让程序更为简洁、清晰。
关于Java8中接口默认方法的介绍就到这里,在后续的文章中我们将介绍Java8中的其它特性。
可以访问个人知乎阅读更多文章:易哥(https://www.zhihu.com/people/yeecode),欢迎关注。