当前位置: 首页 > 面试题库 >

Java 8默认方法会破坏源兼容性吗?

鄢禄
2023-03-14
问题内容

Java源代码通常是向前兼容的。据我所知,在Java 8之前,编译类 源代码都已与更高版本的JDK /
JVM版本向前兼容。[更新:这是不正确的,请参见下面有关“枚举”的注释,等等。]但是,在Java 8中添加了默认方法后,情况似乎不再如此。

例如,我一直在使用的库的实现java.util.List包括一个List<V> sort()。此方法返回已排序列表内容的副本。该库以jar文件依赖项的形式部署,在使用JDK 1.8构建的项目中运行良好。

但是,后来我有机会使用JDK
1.8重新编译该库本身,但发现该库不再编译:List-implementing类及其自己的sort()方法现在与Java 8
java.util.List.sort()默认方法冲突。Java
8的sort()默认方法对列表进行适当排序(返回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

问题答案:

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

超类或接口中的任何新方法都可能破坏兼容性。默认方法使接口更改破坏兼容性的 可能性降低
。从默认方法打开向接口添加方法的角度来看,您可以说默认方法可能会导致某些破坏性的兼容性。

这是第一个这样的向前不兼容的变化吗?

几乎可以肯定不是,因为自Java 1.0以来,我们一直在从标准库中继承类。

在设计和实现默认方法时是否考虑或讨论了此问题? 它记录在任何地方吗?

是的,有人考虑过。请参阅Brian
Goetz在2010年8月发表的论文“通过“公共防御者”方法进行接口演变”:

  1. 源兼容性

如果修改库接口以插入与现有类中的方法不兼容的新方法,则该方案可能会引入源不兼容性。(例如,如果一个类具有浮点值的xyz()方法并实现Collection,并且我们向Collection添加一个整数值的xyz()方法,则现有的类将不再编译。)

(公认的很小的)不便与收益相抵触了吗?

以前,更改接口 肯定会 破坏兼容性。现在,它 可能会
。从“肯定”到“可能”的转变可以被正面或负面地看待。一方面,使向接口添加方法成为可能。另一方面,它打开了您所看到的那种不兼容的大门,不仅与类有关,而且与接口也有关。

但是,正如Goetz论文顶部所引述的,好处大于不便之处:

  1. 问题陈述

一旦发布,就不可能在不破坏现有实现的情况下向接口添加方法。自从库发布以来,时间越长,此限制对其维护者造成痛苦的可能性就越大。

JDK
7中对Java语言的闭包的添加给老化的Collection接口带来了更多压力。闭包最显着的好处之一是,它使开发更强大的库成为可能。添加一种语言功能以启用更好的库同时不扩展核心库以利用该功能将是令人失望的。



 类似资料:
  • 通常情况下,Java源代码是向前兼容的。在Java8之前,据我所知,编译的类和源代码都与后来的JDK/JVM版本实现了前向兼容。[更新:这不正确,请参阅下面的注释re'enum'等。]但是,在Java8中添加了缺省方法之后,情况似乎不再是这样了。 例如,我一直使用的库有一个的实现,它包括一个。此方法返回已排序列表内容的副本。这个库作为jar文件依赖项部署,在使用JDK1.8构建的项目中运行良好。

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

  • 我正在尝试使用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

  • 在Java8中使用缺省方法作为穷人版本的traits是一种安全的做法吗? 有人说,如果你只是为了熊猫而使用它们,可能会让熊猫伤心,因为它很酷,但这不是我的本意。人们还经常提醒说,引入缺省方法是为了支持API演进和向后兼容性,这是真的,但这并不使使用它们作为特征本身是错误的或扭曲的。 我脑海中有以下实际用例: 或者,定义: 关于SO的几个问题与Java vs Scala特性有关;这不是重点。我也不仅