2016-03-15 28 views
7

Przesyłam kod Java7 do Javy 8 i pojawił się następujący problem. W moim kodzie mam dwie metody:Wywołanie metody generycznej Java 8 jest niejednoznaczne.

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 zwraca błąd o niejednoznacznej meczu dla metody Dołącz w następujący test:

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

Błąd kompilatora:

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

Jak przerobić te funkcje na pracę z wnioskiem o typ z wprowadzonego z Java8?

+1

Możesz sprawić, by działał przez 'ImmutableSet obj = null; \t \t ImmutableSet zestaw = ImmutableSet.of (1); \t append (set, obj); '. – Tunaki

+0

Nie można odtworzyć w idee (używając HashSet zamiast ImmutableSet, ale to nie powinno mieć znaczenia z perspektywy inferencji typów) http://ideone.com/oT6SbF. –

+0

@AndyTurner Nie kompiluje się z jdk 1.8.0_51 (i Eclipse Mars.2). – Tunaki

Odpowiedz

7

Znalazłeś nowe, uogólnione udoskonalenia wnioskowania typu docelowego w Javie 8. Jest na nim kilka pytań przepełnienia stosu. Such as this one.

Java 8 może wywnioskować typ zwrotów generycznych na podstawie metody, do której został przekazany jako argument. Tak więc podczas wywoływania CollectionUtils.append(ImmutableSet.of(1), obj), Java 8 próbuje zwrócić niezmienny zestaw ze statycznego połączenia of, które pasuje do jednej z twoich metod append. W tym przypadku może pomyśleć o zwrocie ImmutableSet<Object> zamiast ImmutableSet<Integer>, który wyraźnie próbujesz zwrócić. A potem nie jest jasne, czy dzwonisz pod numer append(Set<Object>, Object) lub append(Set<Integer>, Set<Integer>).

Najprostszym rozwiązaniem jest zmiana nazwy drugiej metody na appendAll. Albo, można postępować zgodnie z zaproponowaną poprawkę here i zmienić swoje powołanie do czegoś takiego:

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

będę trzymać się zmiana nazwy Druga metoda się jednak. Oszczędzi to innym deweloperom ten sam żal, gdy spróbują korzystać z biblioteki.

Powiązane problemy