2016-11-15 15 views
7

Mam funkcję:Dlaczego symbol wieloznaczny w parametrze generycznym wymaga jawnego rzutowania?

<T> T get(Class<T> fetchType) { 
    ... 
} 

Więc jeśli miałbym zrobić coś takiego:

String x = get(String.class); 

To wszystko jest dobre.

Jednak w innej funkcji:

<R> R otherFunction(R base) { 
    return get(base.getClass()); 
} 

daje mi błąd, ponieważ base.getClass() powraca ? extends R.

reason: no instance(s) of type variable(s) exist so that capture of ? extends Object conforms to R 
inference variable T has incompatible bounds: 
equality constraints: capture of ? extends Object upper bounds: Object, R 

Teraz z tego co rozumiem, funkcja get(Class<T> x) zwrotów T, więc kiedy zwanych z ? extends R, który powiedzmy jest CAP#1, ale ponieważ get teraz powraca CAP#1, przypisując go wpisywać R nie powinno być problemem. Aby przetestować to, próbowałem:

Class<? extends CharSequence> stringClass = String.class; 
CharSequence x = get(stringClass); 

To wydaje się działać bez żadnych problemów. Co idzie źle?

EDYTOWANIE: Czy to z powodu usuwania typu, że w czasie wykonywania nie ma informacji o R, ale CharSequence jest? Co nadal nie ma sensu, ponieważ nie jest to sprawdzane wyłącznie podczas fazy kompilacji?

więc okazuje się, że Object.getClass() powraca Class<? extends |X|> a nie Class<? extends X>, gdzie |X| jest wymazanie X dlatego, że pracuje dla konkretnych typów (jak ? extends CharSequence, ale nie dla typu rodzajowego). IntelliJ prawdopodobnie nie zgłasza tego dokładnie, co spowodowało zamieszanie: http://i.imgur.com/yE8LswM.jpg (Próbowałem zrobić zrzut ekranu, ale okno pop-up ciągle znikało).

+1

Pokaż nam kontekst, w którym pojawia się ten błąd. Czy jest to kompilacja 'otherFunction' lub próba wywołania go? Jeśli to drugie, dodaj kod, który go wywołuje. – RealSkeptic

+1

Twój błąd mówi, że 'getClass()' zwraca '? extends Object', kompilator nie może go rozwiązać na '? przedłuża R'. – Codebender

+1

Również, która wersja Java? Java 8 ma lepsze wnioskowanie o typie niż Java 7. – RealSkeptic

Odpowiedz

6

Powód jest opisany w Javadoc z Object.getClass:

public final Class<?> getClass() 

rzeczywisty typ wynik jest Class<? extends |X|> gdzie |X| jest wymazanie statycznego rodzaju ekspresji, na której getClass nazywa.

Więc, kiedy zadzwonić base.getClass() rzeczywisty wynik jest Class<?>, ponieważ wymazywanie R jest Object. To nie jest Class<? extends R>.

+0

To właśnie mnie w tym przypadku pomieszało: http://i.imgur.com/yE8LswM.jpg –

+2

@RohanPrabhu Powiedziałbym, że to błąd w intelli. –

0

Twój parametr R base zezwoli na umieszczenie w tej metodzie wszystkich obiektów twojej żądanej klasy ogólnej < R>, ale także wszystkie obiekty, które są podklasami < R>. Z tego powodu nie wiesz, co się stanie, jeśli wywołasz base.getClass(), oczekujesz < R>, ale może to być również klasa, która rozszerza generyczne R.

+0

Ale przykład 'String' (który jest podklasą z 'CharSequence') działa. – Thilo

+0

Tak, ponieważ powiedziałeś, że to rozszerzona charsequence. Wszystkie możliwe podklasy, które można utworzyć w String, nadal są klasami, które rozszerzają charsequence. –

+1

Co jest w porządku, to oczywiście może być jakakolwiek klasa, która rozszerza 'R', ale ta klasa nadal będzie" przypisywalna "do R, która wydaje się działać idealnie dobrze, gdy robię'? przedłuża CharSequence'. Akceptuje 'String', ale każde wystąpienie' String' nadal można przypisać do 'CharSequence'. –

Powiązane problemy