2014-06-09 15 views
5

le seguenti dichiarazioni:Perché non è possibile assegnare I <? estende Tipo> a <Type>?

URLClassLoader ucl = (URLClassLoader) ClassLoader.getSystemClassLoader(); 
Class<URLClassLoader> uclc = ucl.getClass(); 

con errore:

Type mismatch: cannot convert from Class<capture#2-of ? extends URLClassLoader> to Class<URLClassLoader> 

Perchè ho bisogno di un cast, qui?

Ho trovato diversi post che spiegano il motivo per cui non è possibile fare il contrario (assegnare T a a), ma questo è (tipo) ovvio e comprensibile.

NOTA: Sto codificando questo sotto Eclipse Luna, quindi non so se si tratta di un Luna Quirk o se c'è qualcosa che non capisco davvero nei farmaci generici.

risposta

6

Covariance vs contravariance vs invariance

  • Class<? extends URLClassLoader> è invariante.

Come risultato,

Class<? extends URLClassLoader> è non un sottotipo diClass<URLClassLoader>


In Java una variabile può contenere un riferimento di un'istanza di stesso tipo o sottotipo.

Quindi,

Class<URLClassLoader> uclc = ucl.getClass(); 

è valido.

D'altra parte,

Class<? extends URLClassLoader> uclc = ucl.getClass(); 

sarebbe valida.

+1

Potete eloborate perché 'Classe ' (o '' Classe ) non è un sottotipo di classe '' ? Io penso che sia. – skiwi

+0

@swiki: cerca di pensare in termini di collezioni. Pensi List dovrebbe essere assegnabile alla Lista ? Ciò porterà a problemi di sicurezza del tipo e non è consentito. L'incarico opposto è permesso però. –

+0

Leggi questa fantastica spiegazione: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ503 –

1

Why can't assign I <? extends Type> to <Type>?

perché in realtà <? extends Type> è un supertipo di <Type>! Seguiamo le specifiche.

4.10.2 Subtyping among Class and Interface Types:

Given a generic type declaration C<F1,...,Fn>, the direct supertypes of the parameterized type C<T1,...,Tn> are all of the following:

  • C<S1,...,Sn>, where Si contains Ti.

4.5.1. Type Arguments of Parameterized Types:

A type argument T1 is said to contain another type argument T2, written T2 <= T1, if the set of types denoted by T2 is provably a subset of the set of types denoted by T1 under the reflexive and transitive closure of the following rules:

  • T <= ? extends T

Per questo sappiamo che dal ? extends URLClassLoader contiene URLClassLoader, Class<? extends URLClassLoader> è un supertipo di Class<URLClassLoader>.

Poiché un narrowing reference conversion non è consentito in un assignment context, si verifica un errore di compilazione.

Si noti inoltre che questo significa che l'assegnazione inverso è consentito:

Class<URLClassLoader> concrete = URLClassLoader.class; 
Class<? extends URLClassLoader> wildcard = concrete;