Java的默认接口方法与私有实例方法冲突?

时间:2016-02-25 18:45:14

标签: java interface

据我所知,Java 8的新接口默认方法背后的主要思想是支持接口演进,即扩展接口而不制动现有的实现。

但我刚刚想到的是,实际上API中所有这些新的默认接口方法都有可能破坏现有代码。也就是说,如果我在一个类中实现一个接口X,那么我的实现就会中断,并且接口X现在有一个新的默认方法,它与我已经存在的类的一些私有实例方法具有相同的签名!因为在这种情况下,编译器认为我在覆盖接口方法的同时降低了其可见性,这是​​不允许的。那么,如果我有一些Iterable的实现并想出一些私有的forEach实用工具方法呢?不,当我更新到Java 8时,我无法再编译。

Oracle真的发布了一个不完全向下兼容的API更新,这有点令我感到震惊吗?过去曾经发生过这样的事情,升级到新的编译版本可能会使你的一些代码不再编译?因为如果是这样我就不知道了。你对此有何看法?

编辑:哦,等等,我说的可能有一个缺陷..我用Iterable#forEach方法提到了这个例子,但实际上,这个方法需要一些参数,这个参数也只是用Java 8引入的。所以没有以前我可以定义这种方法的方式。现在,我的下一个问题是:可能是所有新的默认方法都采用了一些新类型来保证它们不会与任何Java-8之前的现有实例方法冲突吗?

干杯

3 个答案:

答案 0 :(得分:4)

Oracle必须在让语言和API停滞不前之间做出选择,或者冒一些后向不兼容的风险。是的,默认方法可能会导致现有扩展接口和实现出现问题。这是众所周知的。

过去是否已经发生过这种情况?是的:JDBC接口有好几次都有新方法。 assert不是关键字,而是Java 1.4之后的关键字等。enum不是1.5之前的关键字等等。

修改

向后不兼容的示例:

如果你有一个扩展Collection的接口MyCollection并且有一个方法stream(),它将与新的默认stream()方法冲突,因为它具有相同的签名但返回类型不同。

如果您有一个扩展/实施List<E>并且方法void sort(Comparator<E> c)的界面或类,它将与新的默认方法void sort(Comparator<? super E>)冲突。

答案 1 :(得分:2)

  

那么如果我有一些Iterable的实现并想出一些私有的forEach实用工具方法怎么办呢?

这不是问题,因为这只会使方法过载。您不能拥有forEach(Consumer),因为此界面之前不存在。

  

Oracle真的发布了一个不完全向下兼容的API更新,这有点令我感到震惊吗?

在每个主要版本中都有可能破坏向后兼容性的更改,在Java 1.4中,添加了关键字enum,这意味着如果您有一个名为enum的变量,它将会中断。

  

过去曾经发生过这样的事情,升级到新的编译版本会使你的一些代码不再编译吗?

某些API已更改,最古老的更改之一是对Java 1.2中String.hashCode()的修复。

答案 2 :(得分:-2)

在我看来,我们的Java开发人员不应该使用这种Default方法。这可能是在不破坏向后兼容性的情况下扩展现有代码的唯一方法。

但这只是我的意见。