Java 8 的默认方法和多重继承
Java 8 的默认方法和多重继承
介绍
我一看到 Java 8 发布了, 就决定开始深入看看对于这门编程语言新的增强功能. 我承认,自己并没有像对待 7 那样对这个版本进行跟进, 所以我所知道的唯一的增强功能只是lambda表达式而已. 在我通读文档,并写下一些示例程序来确保自己对这些新的特性有一个良好的理解是,有一个特性引起了我特别的注意: 默认方法,首先,让我们来看一看它们到底是什么.
先认识认识
从本质上讲,默认方法就是一个在接口里面有了一个实现的方法. 传统的接口只是简单的由抽象方法和公共静态的并且是final的变量构成. 那么考虑看看下面这个:
public interface ExampleInterface { public void exampleMethod(); default public void exampleDefaultMethod() { // Some implementation code here } }
如果一个类决定去实现 ExampleInterface, 它只需要去实现 exampleMethod, 并且它可以简单地采用 exampleDefaultMethod的默认实现. 现在,让我们来看看Oracle打算让我们怎样去使用它们.
它们应该怎么被使用
这个想法不是让你在设计时考虑使用默认方法作为解决方案,而是它们只是一个事后的考虑. 在Oracle的跟踪报道上他们称述的意图是去“确保为那些老版本接口写的代码的二进制兼容性”(1). 从本质上讲,你和你的开发人员编写了对某些接口的多个实现,但是你想要添加新的一块东西. 然而,这样做就意味着对所有那些实现了这个接口的类进行重新构建都将失败,除非你为它们每一个都补上新增的那一块的实现. 默认方法的想法是你可以在不改变现有实现并且再也不用变更它们的前提下加入对接口的新需求.
但是让我们退后一步想想. 这里面还是有些问题的吧. 首先,让我们接受有时高级别 的变更(比如变更你的接口)行将发生的这一事实. 然而,让我们也不要忘了接口的存在的目的是什么. 理想情况下一个接口锁定一些高级别的对象,或者说你是在创造一些特殊功能部分的API. 如果一些类只需要去实现接口功能 的某些部分,而不是全部的话, 那么那会是一个好的设计吗? 那不就是抽象类被设计出来的原因么?
其次,这会引入对于处理多重继承的需求. 而现在谢天谢地,如果你有两个拥有一个对于单个方法签名的默认实现的接口, 而你尝试去拥有一个同时实现这两个接口的类, Java将拒绝编译这个类. 许多人抱怨接口中允许公共静态变量的不确定性,说如果两个接口中有同一个变量就会有些模棱两可(因此像 C# 这样的编程语言就会禁止诸如此类的事情), 而这是有一些难以对付的.
我看到这个功能是如何在这个问题上起作用的, 而我不准备在这里阐述它,直到我看到它被应用在实践中,但是我必须强调它使我感到紧张. 话虽这么说,让我们还是来更多的看看这个功能可能会被运用到的地方,而不是它的这个目的.
可能的误用
前面我们谈到引入多重继承后模棱两可的问题, 那么编译器不会捕捉到的会是什么情况呢? 什么才会使我停止像我使用一个抽象类(通常是一些抽象方法和一些实现)那样,简单的使用接口的做法,而去利用继承多个接口的好处呢? 这没有怎么不好,但是究其自身而言,它将会鼓励使用Java努力避免的复杂设计. 有些情况是在你实际需要多继承来解决你在构建一个抽象类的框架中使用单个继承类型所不能解决的问题.
总结
总的来说,Java8还是提供了许多很酷的新东西的, 有些看起来同Java早期的基础知识相悖. 不管是好是坏,时间会证明一切. 如果你有任何建议,请自由的分享他们. 此外,任何时候开始在你的项目中使用Java 8,请自由分享你的成功或恐怖故事. 可以通过ryan.kenney@coveros.com联系我.
参考
1 – http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html