2016-03-15 10 views
7

Ich portiere Java7-Code zu Java8, und ich kam mit einem folgenden Problem. In meiner Code-Basis habe ich zwei Methoden:Java 8 Aufruf zur generischen Methode ist mehrdeutig

public static <T> ImmutableSet<T> append(Set<T> set, T elem) { 
    return ImmutableSet.<T>builder().addAll(set).add(elem).build(); 
} 

public static <T> ImmutableSet<T> append(Set<T> set, Set<T> elemSet) { 
    ImmutableSet.Builder<T> newSet = ImmutableSet.builder(); 
    return newSet.addAll(set).addAll(elemSet).build(); 

Compiler geben Fehler für Verfahren über zweideutiges Spiel in folgendem Test anfügen:

@Test(expected = NullPointerException.class) 
public void shouldAppendThrowNullPointerForNullSecondSet() { 
    ImmutableSet<Integer> obj = null; 
    CollectionUtils.append(ImmutableSet.of(1), obj); 
} 

Compiler-Fehler:

reference to append is ambiguous both method append(java.util.Set,T) in CollectionUtils and method append(java.util.Set,java.util.Set) in CollectionUtils match

Wie diese Funktionen neu schreiben, um mit Typinferenz zu arbeiten, die mit Java8 eingeführt wurde?

+1

Sie können es mit 'ImmutableSet obj = null; \t \t ImmutableSet set = ImmutableSet.of (1); \t append (set, obj); '. – Tunaki

+0

Kann nicht in ideone reproduzieren (mit HashSet anstelle von ImmutableSet, aber das sollte nicht von einer Art Inferenzperspektive wichtig sein) http://ideone.com/oT6SbF. –

+0

@AndyTurner Es kann nicht mit jdk 1.8.0_51 (und Eclipse Mars.2) kompilieren. – Tunaki

Antwort

7

Sie haben die Verbesserungen für die verallgemeinerte Zieltyp-Inferenz in Java 8 gefunden. Es gibt einige Stapelüberlauffragen. Such as this one.

Java 8 kann den Rückgabetyp eines generischen Objekts basierend auf der Methode ableiten, an die es als Argument übergeben wird. Wenn Sie also CollectionUtils.append(ImmutableSet.of(1), obj) aufrufen, versucht Java 8, einen unveränderlichen Satz aus dem statischen Aufruf of zurückzugeben, der mit einer Ihrer append-Methoden übereinstimmt. In diesem Fall könnte es daran denken, eine ImmutableSet<Object> anstelle der ImmutableSet<Integer>, die Sie eindeutig versuchen, zurückzugeben. Und dann ist es unklar, ob Sie append(Set<Object>, Object) oder append(Set<Integer>, Set<Integer>) aufrufen.

Die einfachste Lösung ist, die zweite Methode appendAll umzubenennen. Oder könnten Sie die vorgeschlagenen fix here folgen und auf Ihren Anruf etwas ändern wie: obwohl

CollectionUtils.append(ImmutableSet.<ImmutableSet<Integer>>of(1), obj); 

ich mit Umbenennung der zweiten Methode selbst haften würde. Es wird anderen Entwicklern die gleiche Trauer ersparen, wenn sie versuchen, die Bibliothek zu benutzen.

Verwandte Themen