5

书中的问题

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

  1. 那有多安全?stream描述接口的新方法Collection导致遗留代码编译失败的场景。
  2. 二进制兼容性怎么样?JAR 文件中的遗留代码是否仍会运行?”

我的答案如下,但我不太确定。

  1. 只有当遗留代码不提供具有相同名称stream和相同签名的方法时(例如,在实现的遗留类中Collection),它才是安全的。否则,这个旧的遗留代码将无法编译。
  2. 我认为保留了二进制兼容性,旧 JAR 文件中的遗留代码仍将运行。但我对此完全没有明确的论据。

任何人都可以确认或拒绝这些答案,或者只是为这些答案添加更多的论点、参考或清晰度吗?

4

1 回答 1

8
  1. 新的stream()默认方法Collection返回 a Stream<E>,也是 Java 8 中的一种新类型。如果遗留代码包含stream()具有相同签名的方法,但返回其他内容,则会导致编译失败,从而导致返回类型冲突。

  2. 只要不重新编译,遗留代码就会继续运行。

首先,在 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();
    }
}

使用-source 1.7 -target 1.7,编译并运行:

$ javac -target 1.7 -source 1.7 Legacy.java MyCollection.java Main.java
$ java Main
foo
Legacy

现在在 1.8 中,我们将流方法添加到MyCollection.

public interface MyCollection
{
    public void foo();
    public default Stream<String> stream() {
        return null;
    }
}

MyCollection我们只在 1.8 中编译。

$ javac MyCollection.java
$ java Main
foo
Legacy

当然我们不能再重新编译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
于 2015-10-14T17:07:33.153 回答