Methodenverweise auf Rohtypen schädlich?

8

Der folgende Code enthält eine Referenz auf Enum::name (no no type parameter).

%Vor%

Javac meldet beim Kompilieren eine Warnung:

  

[WARNUNG] gefunden raw type: java.lang.Enum fehlt Typ Argumente für   generische Klasse java.lang.Enum

Wenn Sie den Ausdruck in Enum<T>::name ändern, wird die Warnung gelöscht.

Allerdings kennzeichnet die Idee die Enum<T>::name Version mit einer Warnung:

  

Explizite Argumenttypen können abgeleitet werden

Umgekehrt meldet Eclipse (ECJ) keine Probleme mit beiden Formulierungen.

Welcher der drei Ansätze ist richtig?

Auf der einen Seite sind rohe Typen eher böse. Wenn Sie versuchen, ein anderes Argument vom Typ z. Enum<Clause>::name wird dazu führen, dass die Kompilierung fehlschlägt, daher gibt es zusätzlichen Schutz.

Andererseits ist die obige Referenz äquivalent zu e -> e.name() lambda, und diese Formulierung benötigt keine Typargumente.

Umgebung:

  • Java 8u91
  • IDEE 15.0.3 Community
  • EuGH 4.5.2
Jakub Bochenski 12.05.2016, 11:36
quelle

1 Antwort

6

Es gibt keine "rohe Methodenreferenz". Zwar gibt es Rohtypen, die die Migration von Code vor der Generierung von Generika unterstützen, es kann jedoch keine Vorgenerics-Verwendung von Methodenreferenzen geben, daher gibt es keinen "Kompatibilitätsmodus", und Typinferenz ist die Norm. Die Java-Sprachspezifikation §15.13. Method Reference Expressions gibt Folgendes an:

  

Wenn eine Methode oder ein Konstruktor generisch ist, können die Argumente des passenden Typs entweder abgeleitet oder explizit angegeben werden. In ähnlicher Weise können die Typargumente eines generischen Typs, die durch den Methodenreferenzausdruck erwähnt werden, explizit oder abgeleitet bereitgestellt werden.

     

Methodenreferenzausdrücke sind immer Polyausdrücke

Während Sie also den Typ vor dem :: als "rohen Typ" aufrufen, wenn er auf eine generische Klasse verweist, ohne Typargumente anzugeben, wird der Compiler dennoch die generische Typ-Signatur gemäß dem Zielfunktionstyp ableiten. Deshalb macht es hier keinen Sinn, eine Warnung vor "roher Typennutzung" zu erstellen.

Beachten Sie, dass z. B.

%Vor%

kann mit javac ohne irgendeine Warnung kompiliert werden (die Spezifikation benennt ähnliche Beispiele, in denen der Typ abgeleitet werden sollte), während

%Vor%

generiert eine Warnung. Die Spezifikation sagt zu diesem Fall:

  

Wenn P1 , ..., Pn nicht leer ist und P1 ein Untertyp von ReferenceType ist, wird der Methodenreferenzausdruck in der zweiten Suche so behandelt, als ob er vorhanden wäre waren ein Methodenaufruf-Ausdruck mit Argumentausdrücken der Typen P2 , ..., Pn . Wenn ReferenceType ein unformatierter Typ ist und eine Parametrisierung dieses Typs vorhanden ist, G<...> , also ein Supertyp von P1 , ist der zu suchende Typ das Ergebnis der Capture-Konvertierung (§5.1. 10) angewendet auf G<...> ; ...

Also sollte der Compiler im obigen Beispiel Enum<Thread.State> als Parametrisierung von Enum verwenden, was ein Supertyp von Thread.State ist, um nach einer geeigneten Methode zu suchen und zum selben Ergebnis wie für das f2 Beispiel zu kommen . Es funktioniert irgendwie , obwohl es die unsinnige Warnung des rohen Typs generiert.

Da javac diese Warnung anscheinend nur dann generiert, wenn sie nach einem geeigneten Supertyp suchen muss, gibt es eine einfache Lösung für Ihren Fall. Verwenden Sie einfach den genauen Typ zum Suchen:

%Vor%

Dies wird ohne Warnung kompiliert.

    
Holger 12.05.2016, 14:20
quelle