【发布时间】:2016-05-08 23:45:02
【问题描述】:
假设我有以下类层次结构:
interface Collection<E>
{
Collection<E> $plus(E element)
}
interface MutableCollection<E> extends Collection<E>
{
@Override
MutableCollection<E> $plus(E element)
}
interface Set<E> extends Collection<E>
{
@Override
Set<E> $plus(E element)
}
interface MutableSet<E> extends Set<E>, MutableCollection<E>
{
@Override
default MutableSet<E> $plus(E element)
{
// ... implementation
}
}
abstract class AbstractArraySet<E> implements Set<E>
{
// ... no $plus(...) implementation
}
class ArraySet<E> extends AbstractArraySet<E> implements MutableSet<E>
{
// ... no $plus(...) implementation
}
如您所见,只有MutableSet 类提供了$plus 方法的实现。在测试用例中,我在 ArraySet 类型的实例上调用此方法。测试总是在 CI 环境中通过,而在我的本地环境中它总是以 AbstractMethodError 失败。在这两种情况下,我都使用 Gradle (2.7)。
错误:
java.lang.AbstractMethodError: Method dyvil/collection/mutable/ArraySet.$plus(Ljava/lang/Object;)Ldyvil/collection/Collection; is abstract
at dyvil.collection.mutable.ArraySet.$plus(ArraySet.java)
at dyvil.tests.CollectionTests.testCollection(CollectionTests.java:99)
at ...
Test Code:
testCollection(new ArraySet());
public void testCollection(Collection collection)
{
assertEquals(mutable.$plus("newElement"), collection.$plus("newElement"));
}
java -version 输出:
-
CI(在哪里工作):
java version "1.8.0" Java(TM) SE Runtime Environment (build 1.8.0-b132) Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode) -
本地(失败的地方):
java version "1.8.0_71" Java(TM) SE Runtime Environment (build 1.8.0_71-b15) Java HotSpot(TM) 64-Bit Server VM (build 25.71-b15, mixed mode)
我预计这是某种javac 错误,编译器无法添加所有必需的桥接方法(代码编译时没有任何警告或错误)。在 IntelliJ IDEA 中,使用 javac 和 Eclipse 编译器都会出现问题。
【问题讨论】:
-
您是否正在展示您已经证明是重现错误的最小设置?这里有很多接口,如果不能用更少的东西来演示,那么问题看起来很复杂。
-
反编译在本地环境中运行时执行的
MutableSet.class。那里有默认方法吗? -
@DraganBozanovic,是的,所有超接口
$plus方法都有桥接方法。不过,ArraySet类中没有桥接方法。 -
“Netbeans with jdk1.8.0_65”没有复制
-
你的项目结构是什么?您在其中进行断言的代码是否与
MutableSet在同一个jar 中?
标签: java interface abstract-methods default-method java-bridge-method