Java 8-默认方法-遗留代码关注点

Java 8-默认方法-遗留代码关注点,java,java-8,default-method,Java,Java 8,Default Method,书中的问题: 在过去(Java8之前),您被告知向接口添加方法是一种不好的形式,因为它会破坏现有代码。现在,您被告知可以添加新方法,前提是您还提供了默认实现 那有多安全?描述一个场景,其中集合接口的新流方法导致旧代码编译失败 二进制兼容性如何?JAR文件中的遗留代码还会运行吗?” 我的回答如下,但我不太确定 只有当旧代码不提供具有相同名称流和相同签名的方法(例如,在实现集合的旧类中)时,它才是安全的。否则,此旧旧旧代码将无法编译 我认为二进制兼容性得到了保留,来自旧JAR文件的遗留代码仍将运行。

书中的问题

在过去(Java8之前),您被告知向接口添加方法是一种不好的形式,因为它会破坏现有代码。现在,您被告知可以添加新方法,前提是您还提供了默认实现

  • 那有多安全?描述一个场景,其中
    集合
    接口的新
    方法导致旧代码编译失败
  • 二进制兼容性如何?JAR文件中的遗留代码还会运行吗?”
  • 我的回答如下,但我不太确定

  • 只有当旧代码不提供具有相同名称
    和相同签名的方法(例如,在实现
    集合
    的旧类中)时,它才是安全的。否则,此旧旧旧代码将无法编译
  • 我认为二进制兼容性得到了保留,来自旧JAR文件的遗留代码仍将运行。但我对此没有明确的论点
  • 是否有人可以确认或拒绝这些答案,或者只是在这些答案中添加更多的论据、参考或清晰

  • Collection
    中新的
    stream()
    默认方法返回一个
    stream
    ,也是Java 8中的一个新类型。如果旧代码包含一个具有相同签名的
    stream()
    方法,但返回其他内容,则编译将失败,从而导致返回类型冲突

  • 旧代码将继续运行,只要它没有重新编译

  • 首先,在1.7中,设置以下内容:

    public interface MyCollection {
        public void foo();
    }
    
    public class Legacy implements MyCollection {
        @Override
        public void foo() {
            System.out.println("foo");
        }
    
        public void stream() {
            System.out.println("Legacy");
        }
    }
    
    public class Main {
        public static void main(String args[]) {
            Legacy l = new Legacy();
            l.foo();
            l.stream();
        }
    }
    
    使用
    -源1.7-目标1.7
    ,编译并运行:

    $ javac -target 1.7 -source 1.7 Legacy.java MyCollection.java Main.java
    $ java Main
    foo
    Legacy
    
    现在在1.8中,我们将stream方法添加到
    MyCollection

    public interface MyCollection
    {
        public void foo();
        public default Stream<String> stream() {
            return null;
        }
    }
    
    当然,我们不能再重新编译
    Legacy.java

    $ javac Legacy.java
    Legacy.java:11: error: stream() in Legacy cannot implement stream() in MyCollection
        public void stream()
                    ^
      return type void is not compatible with Stream<String>
    1 error
    
    $javac Legacy.java
    Legacy.java:11:错误:Legacy中的stream()无法在MyCollection中实现stream()
    公共空流()
    ^
    返回类型void与流不兼容
    1错误
    
    。在保留二进制兼容性的同时这样做是向语言中添加默认方法的主要动机。向现有方法添加默认值是二进制和源代码兼容的;添加具有默认值的新方法是二进制和源代码兼容的(与子类中冲突方法的模交互——这与向非最终类添加新方法具有相同的兼容性特征。)虽然二进制兼容性被保存,但是当它与JRE库行为交互时,仍然可能出现问题,比如,在IN中。您也可以考虑方法可能具有兼容的签名,因此,在没有意愿的情况下,开始重写新的<代码>默认< /代码>方法。t方法;如果向超类中添加的方法与某些子类中的同名方法不兼容,则Java 1.0也会出现同样的问题。向带有默认值的接口添加方法与向类中添加方法具有完全相同的兼容性特征。我认为,与编译器sp相比,冲突方法的问题更小如果签名不冲突,则会出现更大的问题。使用
    stream()
    ,这是不可能的,因为返回类型是一个新类。但是请考虑
    sort(Comparator)
    。在Java 8之前和Java 8之前的自定义
    列表实现中可以有这样一个方法,通过委托给
    集合来实现它。sort
    是合理的。现在,
    Collections.sort
    委托给
    List.sort
    ,Java 8之前的方法无意中覆盖了它。编译器赢了我不能告诉你这个问题…
    $ javac Legacy.java
    Legacy.java:11: error: stream() in Legacy cannot implement stream() in MyCollection
        public void stream()
                    ^
      return type void is not compatible with Stream<String>
    1 error