关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »Java 8中的default方法使用详解

    Java 8中的default方法使用详解

    2015-03-19 00:00:00 出处:stackvoid
    分享

    Java 8支持default方法,ITJS的这篇文章也主要来讲解一下Java 8中default方法的使用方法,比较详细。

    什么是default方法?

    Java 8发布以后,可以给接口添加新方法,但是,接口仍然可以和它的实现类保持兼容。这非常重要,因为你开发的类库可能正在被多个开发者广泛的使用着。而Java 8之前,在类库中发布了一个接口以后,如果在接口中添加一个新方法,那些实现了这个接口的应用使用新版本的接口就会有崩溃的危险。

    有了Java 8,是不是就没有这种危险了?答案是否定的。

    给接口添加default方法可能会让某些实现类不可用。

    首先,让我们看下default方法的细节。

    在Java 8中,接口中的方法可以被实现(Java8中的static的方法也可以在接口中实现,但这是另一个话题)。接口中被实现的方法叫做default方法,用关键字default作为修饰符来标识。当一个类实现一个接口的时候,它可以实现已经在接口中被实现过的方法,但这不是必须的。这个类会继承default方法。这就是为什么当接口发生改变的时候,实现类不需要做改动的原因。

    多继承的时候呢?

    当一个类实现了多于一个(比如两个)接口,而这些接口又有同样的default方法的时候,事情就变得很复杂了。类继承的是哪一个default方法呢?哪一个也不是!在这种情况下,类要自己(直接或者是继承树上更上层的类)来实现default方法(才可以)。

    当一个接口实现了default方法,另一个接口把default方法声明成了abstract的时候,同样如此。Java 8试图避免不明确的东西,保持严谨。如果一个方法在多个接口中都有声明,那么,任何一个default实现都不会被继承,你将会得到一个编译时错误。

    但是,如果你已经把你的类编译过了,那就不会出现编译时错误了。在这一点上,Java 8是不一致的。它有它自己的原因,有于各种原因,在这里我不想详细的说明或者是深入的讨论(因为:版本已经发布了,讨论时间太长,这个平台从来没有这样的讨论)。

    假如你有两个接口,一个实现类。 其中一个接口实现了一个default方法m()。 把接口和实现类一块编译。 修改那个没有包含m()方法的接口,声明m()方法为abstract。 单独重新编译修改过的接口。 运行实现类。

    上面的情况下类可以正常运行。但是,不能用修改过的接口重新编译,但是用老的接口编译仍然可以运行。接下来

    修改那个含有abstract方法m()的接口,创建一个default实现。 编译修改后的接口 运行类:失败。

    当两个接口给同一个方法都提供了default实现的时候,这个方法是无法被调用的,除非实现类也实现了这个default方法(要么是直接实现,要么是继承树上更上层的类做实现)。


    但是,这个类是兼容的。它可以在使用新接口的情况下被载入,甚至可以执行,只要它没有调用在两个接口中都有default实现的方法。

    实例代码:

    为了演示上面的例子,我给C.java创建了一个测试目录,它下面还有3个子目录,用于存放I1.java和I2.java。测试目录下包含了类C的源码C.java。base目录包含了可以编译和运行的那个版本的接口。I1包含了有default实现的m()方法,I2不包含任何方法。

    实现类包含了main方法,所以我们可以在测试中执行它。它会检查是否存在命令行参数,这样,我们就可以很方便的执行调用m()和不调用m()的测试。

    ~/github/test$ cat C.java
    public class C implements I1, I2 {
      public static void main(String[] args) {
        C c = new C();
        if(args.length == 0 ){
            c.m();
        }
      }
    }
    ~/github/test$ cat base/I1.java
    public interface I1 {
      default void m(){
        System.out.println("hello interface 1");
      }
    }
    ~/github/test$ cat base/I2.java
    public interface I2 {
    }

    使用下面的命令行来编译运行:

    ~/github/test$ javac -cp .:base C.java
    ~/github/test$ java -cp .:base C
    hello interface 1

    compatible目录包含了有abstract方法m()的I2接口,和未修改的I1接口。

    ~/github/test$ cat compatible/I2.java
    public interface I2 {
      void m();
    }

    这个不能用来编译类C:

    ~/github/test$ javac -cp .:compatible C.java
    C.java:1: error: C is not abstract and does not override abstract method m() in I2
    public class C implements I1, I2 {
       ^
    1 error

    错误信息非常精确。因为我们有前一次编译获得的C.class,如果我们编译compatible目录下的接口,我们仍然会得到能运行实现类的两个接口:

    ~/github/test$ javac compatible/I*.java
    ~/github/test$ java -cp .:compatible C
    hello interface 1

    第三个叫做wrong的目录,包含的I2接口也定义了m()方法:

    ~/github/test$ cat wrong/I2.java
    public interface I2 {
      default void m(){
        System.out.println("hello interface 2");
      }
    }

    我们应该不厌其烦的编译它。尽管m()方法被定义了两次,但是,实现类仍然可以运行,只要它没有调用那个定义了多次的方法,但是,只要我们调用m()方法,立即就会失败。这是我们使用的命令行参数:

    ~/github/test$ javac wrong/*.java
    ~/github/test$ java -cp .:wrong C
    Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting
    default methods: I1.m I2.m
        at C.m(C.java)
        at C.main(C.java:5)
    ~/github/test$ java -cp .:wrong C x
    ~/github/test$

    结论

    当你把给接口添加了default实现的类库移植到Java 8环境下的时候,一般不会有问题。至少Java8类库开发者给集合类添加default方法的时候就是这么想的。使用你类库的应用程序仍然依赖没有default方法的Java7的类库。当使用和修改多个不同的类库的时候,有很小的几率会发生冲突。如何才能避免呢?

    像以前那样设计你的类库。可能依赖default方法的时候不要掉以轻心。万不得已不要使用。明智的选择方法名,避免和其它接口产生冲突。我们将会学习到Java编程中如何使用这个特性做开发。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    商业智能成CIO优先关注点 技术落地方显成效(1)

    用linux安装MySQL时产生问题破解

    JAVA中关于Map的九大问题

    windows 7旗舰版无法使用远程登录如何开启telnet服务

    Android View 事件分发机制详解

    MySQL用户变量的用法

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。