当前位置: 首页 > 知识库问答 >
问题:

Java8默认方法会破坏源代码兼容性吗?

马国源
2023-03-14

通常情况下,Java源代码是向前兼容的。在Java8之前,据我所知,编译的类和源代码都与后来的JDK/JVM版本实现了前向兼容。[更新:这不正确,请参阅下面的注释re'enum'等。]但是,在Java8中添加了缺省方法之后,情况似乎不再是这样了。

例如,我一直使用的库有一个java.util.list的实现,它包括一个列表 sort() 。此方法返回已排序列表内容的副本。这个库作为jar文件依赖项部署,在使用JDK1.8构建的项目中运行良好。

但是,后来我有机会使用JDK1.8重新编译库本身,发现库不再编译了:带有自己的sort()方法的list实现类现在与Java 8Java.util.list.sort()默认方法冲突。Java8sort()默认方法对列表进行排序(返回void);我的库的sort()方法--因为它返回一个新的排序列表--具有不兼容的签名。

所以我的基本问题是:

  • 由于默认方法,JDK 1.8不是引入了Java源代码的前向不兼容性吗?

还有:

  • 这是第一次这样的前向不兼容更改吗?
  • 在设计和实现默认方法时,是否考虑或讨论了这一点?是否在任何地方记录?
  • 相对于所带来的好处,(承认很小的)不便是否被打折扣了?

下面是一些在1.7下编译运行,在1.8下运行--但不在1.8下编译的代码示例:

import java.util.*;

public final class Sort8 {

    public static void main(String[] args) {
        SortableList<String> l = new SortableList<String>(Arrays.asList(args));
        System.out.println("unsorted: "+l);
        SortableList<String> s = l.sort(Collections.reverseOrder());
        System.out.println("sorted  : "+s);
    }

    public static class SortableList<V> extends ArrayList<V> {

        public SortableList() { super(); }
        public SortableList(Collection<? extends V> col) { super(col); }

        public SortableList<V> sort(Comparator<? super V> cmp) {
            SortableList<V> l = new SortableList<V>();
            l.addAll(this);
            Collections.sort(l, cmp);
            return l;
        }

    }

}

下面显示了正在编译(或失败)并正在运行的代码。

> c:\tools\jdk1.7.0_10\bin\javac Sort8.java

> c:\tools\jdk1.7.0_10\bin\java Sort8 this is a test
unsorted: [this, is, a, test]
sorted  : [this, test, is, a]

> c:\tools\jdk1.8.0_05\bin\java Sort8 this is a test
unsorted: [this, is, a, test]
sorted  : [this, test, is, a]

> del Sort8*.class

> c:\tools\jdk1.8.0_05\bin\javac Sort8.java
Sort8.java:46: error: sort(Comparator<? super V>) in SortableList cannot implement sort(Comparator<? super E>) in List
                public SortableList<V> sort(Comparator<? super V> cmp) {
                                       ^
  return type SortableList<V> is not compatible with void
  where V,E are type-variables:
    V extends Object declared in class SortableList
    E extends Object declared in interface List
1 error

共有1个答案

融唯
2023-03-14

JDK1.8不是由于默认方法而引入了Java源代码的前向不兼容性吗?

超类或接口中的任何新方法都可能破坏兼容性。默认方法降低了接口中的更改破坏兼容性的可能性。从缺省方法打开了向接口添加方法的大门的意义上来说,您可以说缺省方法可能会导致某些兼容性中断。

这是第一次这样的向前不相容的变化吗?

这种方案有可能引入源不兼容,因为库接口被修改以插入与现有类中的方法不兼容的新方法。(例如,如果一个类有一个浮点值的xyz()方法并实现了Collection,而我们向Collection添加了一个int值的xyz()方法,那么现有的类将不再编译。)

相对于好处,(承认很小的)不便是否被打折扣了?

之前换一个接口肯定会破坏兼容性。现在,它可能会。从“肯定”到“可能”,既可以是正面的,也可以是负面的。一方面,它使向接口添加方法变得可行。另一方面,它为您看到的不兼容打开了大门,不只是类,接口也是如此。

    null

一旦发布,就不可能在不破坏现有实现的情况下向接口添加方法。一个库发布的时间越长,这种限制就越有可能给它的维护者造成悲痛。

在JDK7中向Java语言添加闭包对老化的集合接口造成了额外的压力;闭包最重要的好处之一是它允许开发更强大的库。如果添加一个语言特性,使库更好,而同时又没有扩展核心库以利用该特性,那将是令人失望的。

 类似资料:
  • 问题内容: Java源代码通常是向前兼容的。据我所知,在Java 8之前,编译类 和 源代码都已与更高版本的JDK / JVM版本向前兼容。[更新:这是不正确的,请参见下面有关“枚举”的注释,等等。]但是,在Java 8中添加了默认方法后,情况似乎不再如此。 例如,我一直在使用的库的实现包括一个。此方法返回已排序列表内容的副本。该库以jar文件依赖项的形式部署,在使用JDK 1.8构建的项目中运行

  • 主要内容:1 Java8 默认方法的介绍,2 Java8 默认方法的案例1 Java8 默认方法的介绍 Java提供了一种在接口内部创建默认方法的功能。在接口内部定义并带有默认标记的方法称为默认方法。这些方法是非抽象方法。 2 Java8 默认方法的案例 在下面的示例中,Sayable是一个功能接口,其中包含默认值和抽象方法。默认方法的概念用于定义具有默认实现的方法。您还可以覆盖默认方法,以为该方法提供更具体的实现。 输出结果为:  

  • 问题内容: 拥有具有默认方法的接口的动态代理,如何调用默认方法?通过使用类似的方法,您可以得到名为的代理调用处理程序(这在某种程度上是正确的,因为您没有为此接口实现的类)。 我有一个使用ASM来创建实现接口的类并将此类调用委派给此类实例的解决方法。但这不是一个好的解决方案,特别是如果默认方法调用其他接口方法(您将获得委托人乒乓球)。JLS对此问题出人意料地保持沉默… 这里是一个小代码示例: 问题答

  • 我正在尝试使用java 8运行一个Spring hibernate项目。但是面对这个问题 我检查了一下,如果我们在java 8中使用spring 3。*会导致这种情况。但由于我在java 8中使用spring 4。*,所以它不应该发生 pom.xml 如果java 8不再与spring兼容,我们现在无法下载java 7。那么,我们如何将应用程序与java集成呢。 请帮忙

  • 本文向大家介绍Java8新特性之默认方法(default)浅析,包括了Java8新特性之默认方法(default)浅析的使用技巧和注意事项,需要的朋友参考一下 一、什么是默认方法,为什么要有默认方法 简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法。只需在方法名前面加个default关键字即可。 为什么要有这个特性?首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,

  • 我使用远程桌面访问Windows 8 PC。 在我的MVC 4控制器中,我在第一个请求中得到了以下代码: 但当我使用远程桌面登录到Windows 8 PC时,Internet Explorer默认为版本7(兼容性视图): 火狐/4.0 (兼容;微软 7.0;视窗 NT 6.2;哇64;三叉戟/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR