不同 Java 版本的奇怪默认方法行为

Strange Default Method behavior with different Java versions

假设我有以下 class 层次结构:

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 class 提供了$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 输出:


我希望这是某种 javac 错误,其中编译器无法添加所有必需的桥接方法(代码编译时没有任何警告或错误)。在 IntelliJ IDEA 中,使用 javac 和 Eclipse 编译器都会出现问题。

(根据作者上述评论回答:问题已解决):

完全清理和重建也解决了这个问题。

然而,一定是在某个时候涉及到导致二进制文件错误的错误。