2017-03-28 2 views
11

Blick in einer anderen question ich in dieses faszinierende Verhalten der 1.8.0_112 Sun-Oracle-Compiler gestoßen (ich habe mit anderen nicht getestet):Warum beeinflusst die Verwendung von Rohtypvariablen Signaturen ohne Bezug auf Typparameter?

import java.util.List; 

interface Alpha<T> { 
    List<Integer> intList(); 
} 

interface Beta { 
    List<Integer> intList(); 
} 

class Main { 

    public static void main(String[] args) { 

     Alpha rawAlpha = null; 
     Alpha<Character> charAlpha = null; 
     Alpha<?> qmAlpha = null; 
     Beta beta = null; 

     for (Integer i : charAlpha.intList()) {} 
     for (Integer i : qmAlpha.intList()) {} 
     for (Integer i : beta.intList()) {} 
     for (Integer i : rawAlpha.intList()) {} 
    } 
} 

Der Compiler nur for-Schleife in dem letzten fehlschlägt:

error: incompatible types: Object cannot be converted to Integer 
     for (Integer i : rawAlpha.intList()) {} 
            ^
1 error 

Also trotz dieser intList() Rückgabeliste Typ List<Integer> in Alpha hängt nicht von der Art Parameter T, so scheint es, dass die <Integer> Epochen Ed zur Kompilierzeit.

Beachten Sie, dass, wenn wir eine nicht-generische Schnittstelle Beta deklarieren, die theoretisch gleichbedeutend mit der Bezugnahme auf die rohe Alpha wäre, gibt es keine Probleme.

Ist dies das erwartete Verhalten? Kann jemand auf den Absatz über die Sprachspezifikation hinweisen, der diesen Punkt abdecken würde? Wenn dies kein Fehler ist, erscheint es zumindest anti-intuitiv und nicht-produktiv; vielleicht ist es der Vergleichbarkeit halber getan?

+6

Wenn ein generischer Typ als roher Typ verwendet wird, verliert er alle seine Generika, nicht nur die, die von dem Typ abhängen, den Sie nicht angegeben haben. –

+0

@PeterLawrey Ja, das scheint der Fall zu sein, aber die Frage ist warum? –

+1

Ich fragte einen der Entwickler zu dem Zeitpunkt, als Java 5.0 veröffentlicht wurde. Es schien mir, dass es nicht viele Ressourcen gab, um andere Fälle zu unterscheiden, entweder ein roher Typ für Rückwärtskompatibilität oder ein generischer. Es gibt keinen etwas rauhen, aber dennoch gesunden Rückfall. –

Antwort

12

Die JLS Bit, das diese (etwas undeutlich) sagt, ist in JLS 4.8:

Der Typ einer Konstruktor (§8.8), Instanzmethode (§8.4, §9.4) oder nicht-statisches Feld (§8.3) ein rohen Typ C, die nicht von ihren Superklassen oder Superschnitt geerbt wird, ist der Typ, der roh in der generischen Deklaration der Löschung seiner Art entspricht

So C. entspricht, da rawAlpha a ist Rohtyp, der Typ rawAlpha.intList ist die Löschung List<Integer> intList(). Diese Löschung ist List intList().

Warum, ich habe kein Zitat praktisch, aber rohe Typen sind nur wirklich in Java für die Abwärtskompatibilität. Das bedeutet, dass sie nur so gut funktionieren müssen wie vor der Generik; Was Sie verlangen, ist Code, der nur ein bisschen besser funktioniert als früher. Es ist nicht unvernünftig, aber es ist nicht das, wofür sie sich entschieden haben. :-)

+0

mmm ... "ist der rohe Typ, der der Löschung seines Typs in der allgemeinen Deklaration entspricht, die C entspricht" ... Ich würde sagen, dass der Text für Interpretation offen ist. .. also C ist hier '' 'Alpha ' '' oder? so würde Text lesen "der Typ von' '' Alpha.intList''' ist der rohe Typ, der dem Löschen von '' 'List ' '' in der generischen Deklaration entspricht, die '' '' Alpha '' so 'entspricht '' Alpha '' '... Wenn es sich um eine Methode handelte, die als' '' List tList() '' 'deklariert wird, macht der Satz insgesamt Sinn, aber' '' '' 0 Warum löschen '' ' '' 'würde' '' Integer''' hier beeinflussen? –

+2

@ValentinRuano, weil das Löschen von 'List ' 'List' ist - Löschen bedeutet _no_ generische Information wird beibehalten, nicht nur, dass das' T' gelöscht wird. Das ist der gleiche Grund, warum Sie nicht fragen können, ob 'foo instanceof List '. – yshavit

+0

Ich denke, du hast Recht. Ist mir das nur nicht klar, was dieser letzte Teil bedeutet: "in der generischen Deklaration entsprechend C". Es scheint mir, dass, wenn Sie Recht haben (99,9% wahrscheinlich, wenn Sie wollen), dann könnte dieser Teil des Satzes einfach weggelassen werden. Es ist also nicht ausreichend zu sagen, dass das Löschen von '' 'List ' '' '' List''' ist, aber Sie müssen sagen, dass das Löschen von '' 'List ' '' '' 'List' ist '' in der generischen Deklaration entsprechend '' 'Alpha''' so' '' Alpha '' 'was auch immer das bedeutet, das klingt für mich wieder ziemlich unklar. –

Verwandte Themen