Diciamo che ho la seguente gerarchia di classe:strano comportamento Metodo di default con diverse versioni di Java
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
}
Come si può vedere, solo la classe MutableSet
fornisce un'implementazione per il metodo $plus
. In un caso di test, sto chiamando questo metodo su un'istanza di tipo ArraySet
. Il test passa sempre nell'ambiente CI, mentre fallisce sempre con un AbstractMethodError
sul mio ambiente locale. In entrambi i casi, sto usando Gradle (2.7).
l'errore:
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
uscita:
CI (in cui opera):
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)
locale (in cui viene a mancare):
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)
Mi aspetto che questo sia una sorta di javac
bug, in cui il compilatore non riesce ad aggiungere tutti i metodi bridge richiesti (il codice viene compilato senza avvisi o e rrors). In IntelliJ IDEA, il problema si verifica sia utilizzando javac
che il compilatore Eclipse.
Stai presentando quello che hai già dimostrato essere l'installazione minima per riprodurre l'errore? Ci sono molte interfacce qui, se non possono essere dimostrate con meno, il problema sembra piuttosto complesso. –
Decompila il 'MutableSet.class' che viene eseguito in runtime nell'ambiente locale. C'è un metodo predefinito lì? –
@DraganBozanovic, sì, ci sono metodi bridge per tutti i metodi super-interface '$ plus'. Non ci sono metodi bridge nella classe 'ArraySet', però. – Clashsoft