2011-01-28 13 views

Odpowiedz

19

<typearg>methodname jest składnia jednoznacznie określający typ argumentu dla metody rodzajowe

Podczas korzystania rodzajowe klasy, zwykle trzeba określić typ argumentu (np String):

ArrayList<String> list = new ArrayList<String>(); 

W przypadku metody ogólnej zwykle nie podaje się argumentu typu:

public static <T> void foo(T param) { } 
... 
String s = ...; 
MyClass.foo(s); 

Nie zauważysz, gdzie to zrobiliśmy, kod jawnie określa, że ​​chcemy mieć wersję String z foo, tj. Nie było jawnego typu argumentu <String> określonego tak, jak widzieliśmy podczas korzystania z klasy ogólnej (List<String>).

Kompilator robi trochę magii kompilatora, aby wywnioskować ogólny typ argumentu na podstawie kontekstu. To wspaniała rzecz i bardzo potężna.

Jednak od czasu do czasu kompilator nie można wywnioskować argumentów typu automatycznie:

public static <T> void bar() { T myLocalVar = ...; ... } 
MyClass.bar(); 

Jakie konkretne wersja bar my staramy się powołać, to co jest argument typu do tej rozmowy? Dunno? Cóż, kompilator też nie.Musimy wyraźnie określać typ argumentu, tak jak zwykle zrobić przy użyciu rodzajowe Klasa:

MyClass.<String>bar(); 

Zobacz także:


marginesie: może warto wspomnieć, że Java 7 będzie dodanie tzw operator diamentowy, co pozwala nam mieć kompilator wywnioskować argumentów typu przy użyciu klas generycznych teraz też:

ArrayList<String> list = new ArrayList<String>(); 

staje

ArrayList<String> list = new ArrayList<>(); 

What is the point of the diamond operator in Java 7?

8

W ten sposób jawnie określa się parametr typu dla metody ogólnej. W większości przypadków kompilator może to wnioskować, ale czasami musi być jawnie określony.

+0

Dla mojej własnej ciekawości - czy trzeba to wyraźnie stwierdzić, ponieważ te metody są statyczne? – christophmccann

+1

@ Christopher: nie. Działa zarówno w metodach statycznych, jak i niestatycznych. –

+0

Należy to wyraźnie określić, ponieważ jest statyczne, więc nie ma konstruktora, który naprawił argumenty typu ogólnego, a argumentów typu ogólnego nie można wywnioskować z listy parametrów. –

1

powyższych odpowiedzi dość dużo zająć swoje pytanie, ale jeśli chcesz konkretny przykład przypadku, gdy typ rodzajowy wnioskowanie Java nie powiedzie się i expli citly podając go w ten sposób ratuje dzień, należy rozważyć następujące definicje klas:

public class A { } 
public class B extends A { } 
public class C extends A { } 

Następnie poniższy kod działa dobrze (czyli rodzaj wnioskowania Java powiedzie):

List<Class<? extends A>> list = ImmutableList.of(B.class, C.class); 

Ale dla następujących , nie kompiluje:

List<Class<? extends A>> list = ImmutableList.of(B.class); 

Zgadza się; o dziwo, przez usuwania parametr, mylimy system rodzaj wnioskowania, ponieważ „najbliższego wspólnego potomka” z B.class i C.class jest A.class, ale dla B.class przez siebie, to tylko B.class, który (o braku kowariancji w rodzajowych Javy) nie pasuje do List<Class<? extends A>>. W tym przypadku, nie masz wyboru, ale do wykorzystania:

List<Class<? extends A>> list = ImmutableList.<Class<? extends A>>of(B.class); 

Rejestracja B rzeczywiście przedłużenia A, to kompiluje (i działa) po prostu w porządku.

Mam nadzieję, że ta demonstracja podkreśli użyteczność operatora.