W Javie chciałbym mieć coś takiego:
class Clazz<T> {
static void doIt(T object) {
// ...
}
}
Ale rozumiem
Nie można dokonać statycznego odniesienia do niestatycznego typu T.
Nie rozumiem leków generycznych poza podstawowymi zastosowaniami, a zatem nie mam większego sensu. Nie pomaga to, że nie byłem w stanie znaleźć wielu informacji na ten temat w Internecie.
Czy ktoś mógłby wyjaśnić, czy takie użycie jest możliwe w podobny sposób? Ponadto, dlaczego moja pierwotna próba się nie powiodła?
źródło
Java nie wie co
T
jest, dopóki nie utworzysz instancji typu.Może możesz wykonać metody statyczne, wywołując
Clazz<T>.doit(something)
ale brzmi to tak, jakbyś nie mógł.Innym sposobem radzenia sobie z tym jest umieszczenie parametru type w samej metodzie:
co nie zapewnia właściwego ograniczenia U, ale jest lepsze niż nic ....
źródło
Natrafiłem na ten sam problem. Znalazłem odpowiedź, pobierając kod źródłowy do
Collections.sort
frameworku Java. Odpowiedziałem, że użyłem<T>
ogólny w metodzie, a nie w definicji klasy.Więc to zadziałało:
Oczywiście po przeczytaniu powyższych odpowiedzi zdałem sobie sprawę, że byłaby to akceptowalna alternatywa bez użycia klasy ogólnej:
źródło
T extends XXX
składnię.Comparable
. Spróbuj<T extends Comparable<? super T>>
zamiast tego.Można zrobić to, co chcesz, używając składni dla metod ogólnych podczas deklarowania
doIt()
metody (zwróć uwagę na dodanie<T>
międzystatic
ivoid
w podpisie metodydoIt()
):Poprosiłem edytor Eclipse, aby zaakceptował powyższy kod bez
Cannot make a static reference to the non-static type T
błędu, a następnie rozszerzyłem go na następujący program roboczy (wraz z odniesieniami do kultury nieco dostosowanymi do wieku):Które drukuje te linie do konsoli po uruchomieniu:
źródło
<T>
maskuje pierwszy w taki sam sposób, jak wclass C { int x; C(int x) { ... } }
parametrzex
maskuje polex
.static <E extends SomeClass> E foo(E input){return input;}
każdej metody, gdy chciałbym zrobić coś takiegostatic <E extends SomeClass>; //static generic type defined only once and reused
static E foo(E input){return input;}
static E bar(E input){return input;}
//...etc...
Myślę, że ta składnia nie została jeszcze wspomniana (w przypadku, gdy chcesz metodę bez argumentów):
I połączenie:
Mam nadzieję, że komuś to pomoże.
źródło
<String>
ponieważ po prostu wprowadza argument typu, ponieważ przypisujesz go do zmiennej. Jeśli go nie przypisasz, po prostu wnioskujeObject
.Jest to poprawnie wymienione w błędzie: nie można odwoływać się statycznie do niestatycznego typu T. Powodem jest to, że parametr type
T
można zastąpić dowolnym argumentem type, np.Clazz<String>
LubClazz<integer>
itd. Ale wszystkie pola / metody statyczne są wspólne -statyczne obiekty klasy.Poniższy fragment pochodzi z dokumentu :
Jak słusznie zauważył Chris w swojej odpowiedzi , musisz użyć parametru type z metodą, a nie z klasą w tym przypadku. Możesz to napisać w następujący sposób:
źródło
Coś takiego może przybliżyć cię
EDYCJA: Zaktualizowano przykład bardziej szczegółowo
źródło
Gdy określisz typ ogólny dla swojej klasy, JVM wie o tym, że ma tylko instancję klasy, a nie definicję. Każda definicja ma tylko sparametryzowany typ.
Generyczne działają jak szablony w C ++, więc powinieneś najpierw utworzyć instancję swojej klasy, a następnie użyć funkcji z określonym typem.
źródło
Clazz<int>::doIt( 5 )
)Mówiąc prościej, dzieje się tak ze względu na właściwość „Wymaż” generyków. Oznacza to, że chociaż definiujemy
ArrayList<Integer>
iArrayList<String>
, w czasie kompilacji, pozostają jako dwa różne konkretne typy, ale w czasie wykonywania JVM usuwa typy ogólne i tworzy tylko jedną klasę ArrayList zamiast dwóch klas. Więc kiedy zdefiniujemy metodę typu statycznego lub cokolwiek innego dla rodzaju ogólnego, jest ona współdzielona przez wszystkie instancje tego typu ogólnego, w moim przykładzie jest wspólna dla obuArrayList<Integer>
iArrayList<String>
dlatego otrzymujesz błąd. Parametr typu ogólnego nie jest parametrem Dozwolone w kontekście statycznym!źródło
@BD w Rivenhill: Ponieważ w zeszłym roku to stare pytanie zyskało nowe zainteresowanie, kontynuujmy trochę ze względu na dyskusję. Ciało twojej
doIt
metody nie robi nicT
specyficznego. Oto on:Możesz więc całkowicie upuścić wszystkie zmienne typu i po prostu kodować
Dobrze. Wróćmy jednak do pierwotnego problemu. Pierwsza zmienna typu w deklaracji klasy jest redundantna. Potrzebna jest tylko druga metoda. Zaczynamy od nowa, ale to jeszcze nie ostateczna odpowiedź:
Jednak jest to zbyt wielkie zamieszanie o nic, ponieważ następująca wersja działa tak samo. Wszystko czego potrzebuje to typ interfejsu parametru parametru. Nigdzie nie widać żadnych typów zmiennych. Czy to był naprawdę oryginalny problem?
źródło
Ponieważ zmienne statyczne są wspólne dla wszystkich instancji klasy. Na przykład, jeśli masz następujący kod
T jest dostępny tylko po utworzeniu instancji. Ale można zastosować metody statyczne, nawet zanim instancje będą dostępne. Zatem do parametrów typu ogólnego nie można odwoływać się w metodach statycznych i zmiennych
źródło