gpt4 book ai didi

java-8 - 向接口(interface)引入默认方法真的可以保持向后兼容性吗?

转载 作者:行者123 更新时间:2023-12-03 10:29:22 25 4
gpt4 key购买 nike

我想我对在 Java 中为接口(interface)引入默认方法感到有些困惑。据我了解,这个想法是可以在不破坏现有代码的情况下将默认方法引入现有接口(interface)。

如果我用非抽象类实现接口(interface),我(当然)必须定义接口(interface)中所有抽象方法的实现。如果接口(interface)定义了默认方法,我会继承该方法的实现。

如果我实现两个接口(interface),我显然必须实现两个接口(interface)中定义的抽象方法的联合。我继承了所有默认方法的实现;但是,如果两个接口(interface)中的默认方法发生冲突,我必须在我的实现类中重写该方法。

这听起来不错,但是下面的场景呢?

假设有一个接口(interface):

package com.example ;
/**
* Version 1.0
*/
public interface A {
public void foo() ;
/**
* The answer to life, the universe, and everything.
*/
public default int getAnswer() { return 42 ;}
}

和第二个界面
package com.acme ;
/**
* Version 1.0
*/
public interface B {
public void bar() ;
}

所以我可以写以下内容:
package com.mycompany ;
public class C implements com.example.A, com.acme.B {
@Override
public void foo() {
System.out.println("foo");
}
@Override
public void bar() {
System.out.println("bar");
}
public static void main(String[] args) {
System.out.println(new C().getAnswer());
}
}

所以应该没问题,而且确实
java com.mycompany.C 

显示结果 42。

但现在假设 acme.com 对 B 进行以下更改:
package com.acme ;
/**
* Version 1.1
*/
public interface B {
public void bar() ;
/**
* The answer to life, the universe, and everything
* @since 1.1
*/
public default int getAnswer() {
return 6*9;
}
}

据我了解,引入这种方法应该是安全的。但是,如果我现在针对新版本运行现有的 com.mycompany.C,则会收到运行时错误:
Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting default methods: com/example/A.getAnswer com/acme/B.getAnswer
at com.mycompany.C.getAnswer(C.java)
at com.mycompany.C.main(C.java:12)

这并不完全令人惊讶,但这是否意味着向现有接口(interface)引入默认方法总是冒着破坏现有代码的风险?我错过了什么?

最佳答案

即使您通过显式选择将冲突的默认方法调用委托(delegate)给哪个接口(interface)来更新您的实现,这些接口(interface)之一的细微更改仍然可能导致您的代码无法编译。

例如。你可以修复一个类T像这样:

interface I {
default void m() {}
}

interface J {
default void m() {}
}

class T implements I, J {
@Override
public void m() { // forced override
I.super.m(); // OK
}
}

一切都会好起来的,直到发生这样的变化:
interface J extends I {
@Override
default void m() {}
}

如果只有接口(interface) J重新编译,方法 T::m仍将委托(delegate)给 I::m .但是编译 T它本身将不再成功——它将失败并返回 error: bad type qualifier I in default super call :
class T implements I, J { // redundant I, but not an error
@Override
public void m() { // override not necessary, T::m resolves to J::m
I.super.m(); // ERROR
}
}

关于java-8 - 向接口(interface)引入默认方法真的可以保持向后兼容性吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22618493/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com