2012-04-13 20 views
5

Mam metodę, która przyjmuje argument List<?>.Typowe argumenty typu Java

public static String method(List<?> arg){ 
    // Do something based on type of the list 
} 

//I call the method as below 
List<ClassA> listA = new ArrayList<ClassA>(); 
List<ClassB> listB = new ArrayList<ClassB>(); 
method(listA); 
method(listB); 

W method, skąd mam wiedzieć, czy arg jest List z ClassA lub List z ClassB?

+2

Zgłaszanie typu parametru jako '' oznacza dokładnie to, że nie interesuje Cię właściwy typ. – biziclop

+0

duplikat tego http://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list – evanwong

+0

@evanwong - nie jestem pewien, czy zgodziłbym się na jego dupe. – djangofan

Odpowiedz

3

Od odpowiedzi przez użytkownika o nazwie Romain "Jeśli używasz <?>, To znaczy, że nie będą korzystać z sparametryzowanego typ wszędzie. Albo iść do określonego rodzaju (w przypadku wydaje List < String>) lub na bardzo rodzajowy Lista < object> "

również uważam, że jeśli używać ty pytanie oznaczyć niedopasowania typu kompilator przyzwyczajenie złapać aż do czasu wykonywania (reified; str.119 skutecznych Java), z pominięciem skasowaniem i skutecznie eliminując korzyści wynikające z używania rodzajów ogólnych?

ABY odpowiedzieć na pytanie pytającego: jeśli użyjesz List < Obiekt>, a następnie spróbujesz rzucić go do A lub do B, prawdopodobnie używając instanceOf, może to być sposób na określenie, co to jest. Założę się, że jest lepszy sposób na zrobienie tego niż to.

+1

+1 dla OP skutecznie eliminuje korzyści wynikające z używania typów ogólnych – jahroy

+1

oznacza "Nie używam generycznych, ale chcę pozbyć się ostrzeżenia kompilatora." – user949300

+3

-1, ponieważ ta odpowiedź zachęca do złej praktyki kodowania. Zdefiniowanie metody, która przyjmuje ogólny typ argumentu, jest odpowiednią metodą - daje bezpieczeństwo typu i nie wymaga bałaganu. Zobacz odpowiedź jahroy. –

1

Biorąc pod uwagę twój przykład, nie ma sposobu, aby dowiedzieć się, jakie są ogólne typy argumentów dla List. Są usuwane na poziomie instancji.

14

Technicznie rzecz biorąc, ty CAN korzystanie instanceof aby sprawdzić, czy obiekt jest określonego typu.

Jednak ... To jest NOT Dobry pomysł.

Droga już ogłosił swój sposób, może on przyjąć listę dowolnego typu, więc nie koniecznie będzie to albo B.

Trudno powiedzieć, co starasz się zrobić , ale prawdopodobnie powinieneś nadać swojej metodzie charakter ogólny.

Można to zrobić tak:

public static <T> String method(List<T> arg) { 
    // We now know that the type of the list is T, which is 
    // determined based on the type of list passed to this 
    // method. This would demonstrate the point better if 
    // the return type was T, but I'm leaving the return type 
    // as String, because that's what your code returns. 
} 

Oto lepszym przykładem:

Jeśli chcesz stworzyć ogólną metodę, która zwraca pierwszy element na liście, zrobiłby to tak:

public static <T> T firstElement(List<T> theList) { 
    if (theList == null) { 
     return null; 
    } 
    T objectOfTypeT = theList.get(0); 
    return objectOfTypeT; 
} 

Pamiętaj, że zwrot typ jest teraz T.

Ponieważ stworzyliśmy tę metodę ogólną, może ona zwrócić ten sam typ, który jest używany na liście.

Zazwyczaj po prostu wrócisz theList.get(0), ale dodałem linię, aby cel ogólny był bardziej oczywisty.

Wyjaśnienie składni:

  • <T> wskazuje, że metoda ta przyjmuje jeden parametr typu o nazwie T.

  • T że natychmiast następuje to rodzaj powrotu (tak jak normalnie return String, Integer, etc ...).

  • Parametr List jest parametrem T określającym, w jaki sposób kompilator wie, co do cholery jest T.

Pozwala to kompilator powiedzieć: "Ta metoda oczekuje coś typu T. O popatrz ... Lista jest również typu T. Jeśli ktoś przechodzi listę ciągów do tej metody, niż T musi być ciągiem. Jeśli ktoś przechodzi listę liczb całkowitych do tej metody, T musi być liczbą całkowitą. "

Natomiast metoda może tylko powrócić ciąg znaków i nie ma pojęcia, jaki typ jest używany w Lista.


także ...

Jeżeli A i B przedłużyć tę samą klasę o nazwie TheParentClass, można zadeklarować metodę tak:

public static String method(List<? extends TheParentClass> arg) 

w ten sposób, że wiesz trochę więcej o możliwych typach twojego parametru (i może skorzystać z sprawdzania czasu kompilacji).

+0

Ten ostatni przykład, który dałeś z "? Extends TheParentClass" jest prawdopodobnie taki jak? było "przeznaczone" do użycia. Zezwalanie na używanie? bez przedłużania to, jak sugeruje David Mason, zła praktyka, ale legalna. Myślę, że jahroy powinien otrzymać odpowiedź na to pytanie, a nie na mnie, ponieważ go przybijał. – djangofan

Powiązane problemy