什么是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是不一致的。它有它自己的原因,有于各种原因,在这里我不想详细的说明或者是深入的讨论(因为:版本已经发布了,讨论时间太长,这个平台从来没有这样的讨论)。
1.假如你有两个接口,一个实现类。
2.其中一个接口实现了一个default方法m()。
3.把接口和实现类一块编译。
4.修改那个没有包含m()方法的接口,声明m()方法为abstract。
5.单独重新编译修改过的接口。
6.运行实现类。
上面的情况下类可以正常运行。但是,不能用修改过的接口重新编译,但是用老的接口编译仍然可以运行。接下来
1.修改那个含有abstract方法m()的接口,创建一个default实现。
2.编译修改后的接口
3.运行类:失败。
当两个接口给同一个方法都提供了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编程中如何使用这个特性做开发。
更多Java8的default方法详细介绍相关文章请关注PHP中文网!

本文讨论了使用Maven和Gradle进行Java项目管理,构建自动化和依赖性解决方案,以比较其方法和优化策略。

本文使用Maven和Gradle之类的工具讨论了具有适当的版本控制和依赖关系管理的自定义Java库(JAR文件)的创建和使用。

本文讨论了使用咖啡因和Guava缓存在Java中实施多层缓存以提高应用程序性能。它涵盖设置,集成和绩效优势,以及配置和驱逐政策管理最佳PRA

本文讨论了使用JPA进行对象相关映射,并具有高级功能,例如缓存和懒惰加载。它涵盖了设置,实体映射和优化性能的最佳实践,同时突出潜在的陷阱。[159个字符]

Java的类上载涉及使用带有引导,扩展程序和应用程序类负载器的分层系统加载,链接和初始化类。父代授权模型确保首先加载核心类别,从而影响自定义类LOA

本文解释了用于构建分布式应用程序的Java的远程方法调用(RMI)。 它详细介绍了接口定义,实现,注册表设置和客户端调用,以解决网络问题和安全性等挑战。

本文详细介绍了用于网络通信的Java的套接字API,涵盖了客户服务器设置,数据处理和关键考虑因素,例如资源管理,错误处理和安全性。 它还探索了性能优化技术,我

本文详细介绍了创建自定义Java网络协议。 它涵盖协议定义(数据结构,框架,错误处理,版本控制),实现(使用插座),数据序列化和最佳实践(效率,安全性,维护


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

WebStorm Mac版
好用的JavaScript开发工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

Atom编辑器mac版下载
最流行的的开源编辑器