java默认代码地址

乍一看, 默认方法为Java虚拟机的指令集带来了一个很棒的新功能。 最后,库开发人员能够开发已建立的API,而不会对其用户代码造成不兼容性。 使用默认方法,当将新方法引入该接口时,任何实现库接口的用户类都会自动采用默认代码。 而且,一旦用户更新了自己的实现类,他就可以使用对他的特定用例更有意义的东西来覆盖默认值。 更好的是,用户可以从重写的方法中调用接口的默认实现,并在其周围添加逻辑。

到目前为止,一切都很好。 但是,将默认方法添加到已建立的接口会使Java代码无法编译。 在查看示例时,这是最容易理解的。 让我们假设一个库需要其接口之一的类作为输入:

interface SimpleInput {void foo();void bar();
}abstract class SimpleInputAdapter implements SimpleInput {@Overridepublic void bar() {// some default behavior ...}
}

在Java 8之前,接口和相应适配器类的上述组合是Java编程语言中相当普遍的模式。 图书馆供应商通常会提供适配器,以节省图书馆用户的键入时间。 但是,还额外提供了接口,以允许近似多重继承。

让我们进一步假设用户使用了此适配器:

class MyInput extends SimpleInputAdapter{@Overridepublic void foo() {// do something ...}@Overridepublic void bar() {super.bar();// do something additionally ...}
}

通过此实现,用户最终可以与库进行交互。 请注意,该实现如何覆盖bar方法以向默认实现添加一些功能。

那么,如果库迁移到Java 8,会发生什么呢? 首先,该库很可能会弃用适配器类,并将功能移至默认方法。 结果,该接口现在将如下所示:

interface SimpleInput {void foo();default void bar() {// some default behavior}
}

使用此新界面,用户可以更新其代码以适应默认方法,而不必使用适配器类。 使用接口而不是适配器类的最大好处是能够扩展除特定适配器之外的其他类。 让我们付诸实践,并迁移MyInput类以使用默认方法。 因为我们现在可以扩展另一个类,所以让我们另外扩展一些第三方基类。 这个基类的作用在这里并不特别相关,因此让我们假设这对我们的用例有意义。

class MyInput extends ThirdPartyBaseClass implements SimpleInput {@Overridepublic void foo() {// do something ...}@Overridepublic void bar() {SimpleInput.super.foo();// do something additionally ... }
}

为了实现与原始类中类似的行为,我们利用Java 8的新语法来调用特定接口的默认方法。 同样,我们将myMethod的逻辑移到了一些基类MyBase 。 拍拍我们的肩膀。 很好的重构!

我们正在使用的库取得了巨大的成功。 但是,维护人员需要添加另一个接口以提供更多功能。 此接口表示一个CompexInput ,它使用其他方法扩展了SimpleInput 。 因为默认方法通常被认为可以安全添加 ,所以维护者还重写了SimpleInput的默认方法,并添加了一些行为以提供更好的默认值。 毕竟,在实现适配器类时,这样做很普遍:

interface ComplexInput extends SimpleInput {void qux();@Overridedefault void bar() {SimpleInput.super.bar(); // so complex, we need to do more ...}
}

这项新功能非常强大,以至ThirdPartyBaseClass的维护者决定也依赖此库。 为此,他为ThirdPartyLibrary实现了ComplexInput接口。

但这对MyInput类意味着什么? 由于通过扩展ThirdPartyBaseClass隐式实现ComplexInput ,调用SimpleInput的默认方法突然变得非法。 结果,用户的代码不再编译。 另外,现在通常禁止调用此方法,因为Java认为此调用与调用间接超类的super-super方法一样是非法的。 相反,您可以调用
ComplexInput类。 但是,这需要您首先在MyInput显式实现此接口。 对于图书馆的用户来说,这种变化很有可能是出乎意料的!

奇怪的是,Java运行时并没有区别。 JVM的验证程序将允许已编译的类调用SimpleInput::foo即使已加载的类在运行时通过扩展ThirdPartyBaseClass的更新版本隐式实现了ComplexClass 。 这里只有编译器抱怨。

但是我们从中学到什么呢? 简而言之,请确保不要在另一个接口中覆盖默认方法。 既不使用其他默认方法,也不使用抽象方法。 通常,请小心使用默认方法。 它们可以像Java的collection接口一样轻松地简化已建立的API的演变,但它们本身却很复杂,因为它们允许执行类型层次结构中的方法调用。 在Java 7之前,您只需要通过遍历线性类层次结构来查找实际调用的代码。 仅当您确实觉得有必要时才添加这种复杂性。

翻译自: https://www.javacodegeeks.com/2014/05/java-8-default-methods-can-break-your-users-code.html

java默认代码地址

java默认代码地址_Java 8默认方法可能会破坏您的(用户)代码相关推荐

  1. Java 8默认方法可能会破坏您的(用户)代码

    乍一看, 默认方法为Java虚拟机的指令集带来了一个很棒的新功能. 最后,库开发人员能够开发已建立的API,而不会对其用户代码造成不兼容性. 使用默认方法,当将新方法引入该接口时,任何实现库接口的用户 ...

  2. java 反射 获取 实例_java通过类反射获取某个类的所有信息--代码实例

    package huang.de.wei; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; ...

  3. Java 中array.size()_Java ArrayDeque size()方法与示例

    ArrayDeque类size()方法size()方法在java.lang包中可用. size()方法用于返回存储在此双端队列中的大小(元素数). size()方法是一个非静态方法,只能通过类对象访问 ...

  4. java 获取http地址_java如何获取当前时间,java如何获取ip地址

    展开全部 获取当前时间public static void main(String[] args) throws IOException { SimpleDateFormat format = new ...

  5. java printstream 覆盖了_Java PrintStream clearError()方法与示例

    PrintStream ClassclearError()方法clearError()方法在java.io包中可用. clearError()方法用于清除此PrintStream的内部错误状态. cl ...

  6. java中扫描仪程序_Java扫描仪delimiter()方法及示例

    扫描仪类delimiter()方法delimiter()方法在java.util包中可用. delimiter()方法用于检索当前与分隔符匹配的Scanner的模式. delimiter()方法是一种 ...

  7. java使用drawtext重叠_Java Graphics.drawText方法代碼示例

    本文整理匯總了Java中org.eclipse.draw2d.Graphics.drawText方法的典型用法代碼示例.如果您正苦於以下問題:Java Graphics.drawText方法的具體用法 ...

  8. java arraylist初始大小_Java - ArrayList默认初始值

    当您在Java中创建Integer类型的数组列表时,默认值是什么?我需要检查一个数组列表是否已满,然后我将获取数组的大小,然后获取最后一个索引处的值,并检查它是否为默认值.Java - ArrayLi ...

  9. JAVA里tokens意思_Java TokenMetadata.sortedTokens方法代码示例

    import org.apache.cassandra.locator.TokenMetadata; //导入方法依赖的package包/类 /** * Get the "primary r ...

最新文章

  1. 现代计算机三大科学计算,计算机的三大特点是什么?
  2. windows 启用远程服务
  3. C# Interlocked 笔记
  4. Recurrent Neural Network系列2--利用Python,Theano实现RNN
  5. 字节跳动AI科学家王崇学生时代论文获“时间检验研究奖”
  6. 如何使用 React 和 React Hooks 创建一个天气应用
  7. JQuery AJAX基本使用
  8. Redis(1)---五种数据结构
  9. 基于ebpf的防火墙--bpf-iptables
  10. java接口之双端队列
  11. 如何在桌面添加计算机日历工具,Win7电脑在桌面添加时钟、日历、货币、天气、CPU仪表盘小工具方法...
  12. GAMIT处理GLONASS数据
  13. \r,\n,\r\n的区别
  14. Canonical Coordinate System
  15. 耳机在电脑上测试有声音,但是网页和视频没有声音
  16. 精品微信小程序ssm电影院购票+后台管理系统|前后分离VUE
  17. cent7 安装 notepadqq
  18. Jekyll 教程——合集(collections)
  19. 一维亥姆霍兹线圈设计磁场250Gs
  20. 谷歌深度神经网络_本周关注我们:轻松阅读,神经网络和Google召集不良网站

热门文章

  1. 洛谷UVA1328,POJ1961-Period【KMP,字符串】
  2. jzoj3462-休息【归并排序,逆序对】
  3. 案例分析 | 由Decimal操作计算引发的Spark数据丢失问题
  4. 这可能是把Docker的概念讲的最清楚的一篇文章
  5. 这些保护Spring Boot 应用的方法,你都用了吗?
  6. Jsoup代码解读之七-实现一个CSS Selector
  7. Java 8新特性探究(二)深入解析默认方法
  8. 《四世同堂》金句摘抄(十六)
  9. 维护win10注册表
  10. 二维数组常用的赋值方式