2014-06-09 14 views
5

Die folgenden Aussagen:Warum kann ich nicht I <? erweitert Typ> auf <Type>?

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

mit Fehler fehlschlagen:

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

Warum brauche ich eine Besetzung, hier?

Ich habe mehrere Beiträge gefunden, die erklären, warum Sie nicht das Gegenteil tun können (T zu a zuordnen), aber das ist (irgendwie) offensichtlich und verständlich.

HINWEIS: Ich kodiere dies unter Sonnenfinsternis Luna, also weiß ich nicht, ob es eine Luna Quirk ist oder ob ich etwas wirklich nicht verstehe in Generika.

Antwort

6

Covariance vs contravariance vs invariance

  • Class<? extends URLClassLoader> ist invariant.

Als Ergebnis

Class<? extends URLClassLoader> ist kein Subtyp vonClass<URLClassLoader>


In Java eine Variable eine Referenz von einer Instanz von gleichen Typs oder Subtyps halten kann. Daher

,

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

ist ungültig.

Auf der anderen Seite,

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

würde gültig sein.

+1

Können Sie warum 'Klasse ' eloborate (oder 'Klasse ') ist kein Subtyp von 'Klasse '? Ich denke, es ist. – skiwi

+0

@swiki: Versuchen Sie, in Bezug auf Sammlungen zu denken. Denkst du List sollte der Liste zuweisbar sein? Dies führt zu Sicherheitsproblemen und ist nicht erlaubt. Die umgekehrte Zuordnung ist jedoch erlaubt. –

+0

Lesen Sie diese fantastische Erklärung: http://www.angelikananger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ503 –

1

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

Denn eigentlich <? extends Type> ist ein übergeordneter Typ von <Type>! Folgen wir der Spezifikation.

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

Wir wissen daher, dass seit ? extends URLClassLoaderURLClassLoader enthält, Class<? extends URLClassLoader> ein übergeordneter Typ von Class<URLClassLoader> ist.

Da ein narrowing reference conversion innerhalb einer assignment context nicht zulässig ist, tritt ein Kompilierungsfehler auf.

Beachten Sie auch, dass dies bedeutet, dass die umgekehrte Zuordnung erlaubt ist:

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