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

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

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

interface SimpleInput {
  void foo();
  void bar();
}

abstract class SimpleInputAdapter implements SimpleInput {
  @Override
  public void bar() {
    // some default behavior ...
  }
}

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

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

class MyInput extends SimpleInputAdapter{
  @Override
  public void foo() {
    // do something ...
  }
  @Override
  public 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 {
  @Override
  public void foo() {
    // do something ...
  }
  @Override
  public void bar() {
    SimpleInput.super.foo();
    // do something additionally ... 
  }
}

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

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

interface ComplexInput extends SimpleInput {
  void qux();
  @Override
  default 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-商城收货地址代码 电商网站增加删除收货地址代码!!!!!!!!!!1! 立即下载

相关推荐

基于vue.js仿淘宝收货地址并设置默认地址的案例分析

主要介绍了基于vue.js仿淘宝收货地址并设置默认地址的案例分析,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

设置默认收货地址

设置默认收货地址 持久层 SQL语句的规划 1.检测当前用户设置为默认收货地址的这条数据是否存在。 select * from t_address where aid=? 2.在修改用户的收货默认地址前,先将所有的收货地址设置为非默认。 update t_address set is_default=0 where uid=? 3.将用户当前选中的这条数据设置为默认收货地址。 update t_address set is_default=1,modified_user=?,modified_time

weixin_45427945的博客 2564

vue设置默认收货地址代码

vue设置默认收货地址代码是一款购物商城平台常用的默认收货地址选择效果,在地址列表中选择一个设置为默认地址。

设置默认收货地址【项目 商城】

设置默认收货地址【项目 商城】

小心星的博客 2543

国内在线查看Java源码(支持下载)

终于建了一个自己个人小站:https://huangtianyu.gitee.io,以后优先更新小站博客,欢迎进站,O(∩_∩)O~~       现在的IDE都很强大都能直接通过按Ctrl+鼠标左键查看Java源码,但是当你没有IDE时,查看源码就会变得很困难。这里提供了网上查看Java源码的方法。       首先给出源码地址:https://gitee.com/huangtianyu/j...

hty1053240123的专栏 4万+

怎么查看Java的源代码

希望下面我的讲解对你有所帮助,谢谢! Java的源代码 对于学习java的你来说,肯定对下面的代码并不陌生 我们都知道,这是导入相应的依赖文件。但是,你真的了解它嘛? 或许你会和我一样,对这个文件很好奇,这个文件到底长什么样子呢?这个文件又在哪里呢?它又是如何实现的呢? 其实对于这些问题,我们只要找到 java.util.Scanner 对应的根目录文件就可以在后面学习 java 的路上慢慢去解决它们了。那我就长话短说,这个文件其实就在我们相应的JDK中,在JDK文件下的src.zip里面,我的详细根目录

正_函数的博客 5595

java默认代码地址_Java 8默认方法可能破坏您的(用户代码

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

最佳 Java 编程 244

java破坏_Java 8默认方法破坏你的(用户的)代码

Java 8默认方法试图尝试更进一步简化Java API。不幸的是,这一最近的语言扩展带来了一系列复杂的规则,但只有少部分Java开发者意识到这一点。这篇文章告诉你为什么引入默认方法破坏你的(用户)代码。起初看来,默认方法Java虚拟机的指令集带来了很多新的特性。最终,开发库的人能够在不带来客户端代码的兼容性问题的情况下,升级API。使用 默认方法,任何实现库接口的类都自动适应接口引入的默...

weixin_35710941的博客 103

Java8:纠结的默认方法

【编程导论(Java)·4.3Java接口】 Java8中引入的默认方法,充分展示了Java平台概念的一致性与JDK向前兼容之间的矛盾

yqj2065的博客 7554

java多重身份登录界面代码_Java 8默认方法破坏你的(用户的)代码

Java 8默认方法试图尝试更进一步简化Java API。不幸的是,这一最近的语言扩展带来了一系列复杂的规则,但只有少部分Java开发者意识到这一点。这篇文章告诉你为什么引入默认方法破坏你的(用户)代码。起初看来,默认方法Java虚拟机的指令集带来了很多新的特性。最终,开发库的人能够在不带来客户端代码的兼容性问题的情况下,升级API。使用默认方法,任何实现库接口的类都自动适应接口引入的默认...

weixin_35330796的博客 248

java8中接口方法默认方法、static静态方法

1、概述 以前,接口里的方法要求全部是抽象方法java8以后允许在接口里定义默认方法和类方法。不同的是: 默认方法可以通过实现接口的类实例化的对象来调用,而类方法就相对于工具方法了。需要注意的是,此处的静态方法只能被public修饰(或者省略不写),不能是private或者protected java8可以说是jdk版本的一次重大升级,给我们也带来了非常多的新特性,而本文就针对于java...

一线工作者的所见、所闻...... 2万+

浅谈JAVA8引入的接口默认方法

浅谈JAVA8引入的接口默认实现 JAVA接口基础 接口定义 在JAVA中,接口的作用主要是定义该类型实例具有的功能,也就是定义必须执行那些工作,而不关心如何进行这些工作。所以,在接口中定义的方法没有方法体,并且接口不允许定义实例变量。以下代码中定义名为MyInterface的接口,并且在该接口中定义了getInt方法,如果有类实现了该接口,则根据JAVA语法,该类必须实现getIn

行者 1万+

Java 8 接口的默认方法和静态方法

Java 8中,接口得到了一些重要的更新,其中包括引入了默认方法和静态方法的概念。默认方法允许在接口中提供默认实现,而静态方法则允许在接口中定义静态方法。这些新特性为Java的接口增加了更多的灵活性和功能。本教程将介绍Java接口的默认方法和静态方法的概念和用法。

qq_38766930的博客 1546

Java8默认方法

1、为什么要有默认方法java 8 之前,接口与其实现类之间的 耦合度 太高了(tightly coupled),当需要为一个接口添加方法时,所有的实现类都必须随之修改。默认方法解决了这个问题,它可以为接口添加新的方法,而不会破坏已有的接口的实现。 例如,Java8的List接口新增了sort方法。在Java8之前,则每个实现了List接口的类必须定义sort方法的实现,或者从父类中继承它的...

大鹏小站的博客 363

SpringBoot-项目2-收货地址(新增,修改,删除,设为默认收货地址)

关于收货地址数据的功能分析 在处理收货地址数据时,需要完成的功能有:新增收货地址、显示收货地址列表、编辑收货地址、删除收货地址、将此收货地址设为默认。 以上功能的开发顺序应该是:增加 > 显示列表 > 设为默认 > 删除 > 编辑。 26. 收货地址-创建数据表 创建收货地址的数据表: # 注意:以下没有添加相应的非空not null约束 create table t_a...

zhangxuelong461的博客 2万+

设置默认地址

设置默认地址 在适配器里写这个方法 修改并再次查询地址后 调用这个方法 //改变默认值 public void setAllunCheck(int position) { int size = list.size(); for (int i=0;i<size;i++){ if(i==position){ ...

weixin_43218083的博客 2554
上一篇: RSS阅读器使用:ROME,Spring MVC,嵌入式Jetty
下一篇: 为Lucene选择快速唯一标识符(UUID)
dnc8371
博客等级 码龄11年 421粉丝 0原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值