2014-10-08 8 views
5

Ich habe eine Methode, deren erklärtes Argument ist Subtyp von Number wie unten angegeben:Wildcard-in-Methode Argument

public static void organizeData(java.util.List<? extends Number> c) { 
    //operation on the list 
} 

Ich bin der Lage, alle nicht-parametrisierte Listen als Argument übergeben. Also, was ist der Sinn der Verwendung von Wildcard <? extends Number>?

List newList = new LinkedList<>(); 
ClassName.organizeData(newList); 

Warum erhalte ich Element vom Typ Object von c? Und nicht vom Typ Number? Gibt es eine Möglichkeit, nur Subtypen eines Typs als Argumente übergeben zu können, anstatt nichtparametrisierte Argumente zuzulassen?

+5

Sie können das nicht verhindern. Ein Benutzer kann immer zuerst auf den Raw-Typ und dann auf das Erforderliche umstellen. Generika haben ihre Grenzen und Raws brechen sie immer. –

Antwort

6

Sie stellen drei Fragen hier, ich werde sie getrennt beantworten. By the way, würden Sie finden es wertvoll, die Java Generics FAQ - considered by many to be the canonical reference on the subject zu lesen:

  1. Also, was ist der Punkt, der Wildcard <? extends Number> mit?

Sie müssen die Platzhalter für die Zeiten verwenden, wenn die parametrisierte Argument eine Unterklasse von Number ist, sagen wir, Integer. Zum Beispiel:

import java.util.LinkedList; 
import java.util.List; 

public class NumberTest { 
    public static void main(String... args) { 
     List<Integer> newList = new LinkedList<Integer>(); 
     organizeData(newList); // This works! 
     anotherMethod(newList); // Doesn't compile 
    } 

    private static void organizeData(List<? extends Number> list) { 

    } 

    private static void anotherMethod(List<Number> list) { 

    } 
} 

Der zweite Methode Aufruf mit dem Übersetzungsfehler fehlschlägt:

NumberTest.java:9: error: method anotherMethod in class NumberTest cannot be applied to given types; 
         anotherMethod(newList); // Doesn't compile 
         ^
    required: List<Number> 
    found: List<Integer> 
    reason: actual argument List<Integer> cannot be converted to List<Number> by method invocation conversion 
1 error 

  1. Warum erhalte ich Element vom Typ Object von c ? Und nicht vom Typ Number?

Der Grund, warum Sie eine Art Object in Ihrem zweiten Fall bekommen ist, weil you are using the Raw Type. Sie sollten niemals eine rohe Art verwenden, wenn Sie es aus diesem Grund vermeiden können - Sie verlieren alle Vorteile der Compiler Typprüfung.


  1. Gibt es eine Möglichkeit nur Subtypen einen Typen zu ermöglichen, als Argument zu ermöglichen nichtparametrisierter Argumente auch im Gegensatz weitergegeben werden?

Sie können Heap Pollution in der Art und Weise nicht verhindern, dass Sie beschreiben, weil jemand immer auf den Raw-Typ gegossen und dann auf alles, was erforderlich ist. Generics sind nur ein Kompilierzeitkonstrukt und are ultimately erased after compilation. Deshalb kann die ungeprüfte Typkonvertierung Warnung nur durch Annotation unterdrückt werden.

1

Sie müssen sich daran erinnern, dass in Java-Generika ein Kompilierzeitkonstrukt zur Unterstützung der Typsicherheit vorhanden ist. Zur Laufzeit konvertiert type desaturage alle generischen Typen in Object und fügt bei Bedarf Casting hinzu. Wenn Sie die Kompilierzeitüberprüfung umgehen, indem Sie Raw-Typen verwenden (für die der Compiler eine Warnung ausgibt), haben Sie den Vorteil von Generika umgangen (Kompilierzeittypprüfung und sicheres Casting für die Laufzeit).

0

Generics in Java werden über Type Erasure implementiert. ich.e: Geben Sie Informationen ein, die Sie in <> angeben, die zur Laufzeit nicht vorhanden sind. Während der Kompilierzeit nutzt der Java-Compiler die Informationen in <> um sicherzustellen, dass alles in Ordnung ist. Wenn Sie jedoch den Typ in <> nicht angeben, wie Sie es für die Variable 'newList' getan haben, hindert Sie nichts daran, es an die Methode 'organizeData' zu übergeben.