Hej.
public class Player<T> implements User<T>
Czy dam rady w jakiś sposob w definicji wyłukać nazwe klasy konkretnej T ? np. mam tam metode ktora ma sie zachowac w inny sposob w zaleznosci od typu T.
Hej.
public class Player<T> implements User<T>
Czy dam rady w jakiś sposob w definicji wyłukać nazwe klasy konkretnej T ? np. mam tam metode ktora ma sie zachowac w inny sposob w zaleznosci od typu T.
Nie. Java ma type erasure. W trakcie wykonania programu nie ma informacji o typie. Oczywiście jeśli masz gdzieś w Player pole typu T to możesz sobie je wyciągnąć i refleksja odczytać nazwę klasy, ale to zły pomysł. Na oko masz błąd w projekcie. Napisz konkretnie co robisz i co chcesz osiągnąć.
Chce w pewnym momencie w klasie Player wykonac np. cos takiego:
entityManager.createQuery("from **T**").getResultList()
Zeby nie tworzyc DAO dla kazdej z podklas.
Możesz po prostu przekazać obiekt typu java.lang.Class
, który ma metodę getSimpleName(). Żeby go dostać zastosuj składnię typu Klasa.class
, bądź obiekt.getClass()
.
A jak możesz to ort! się na spring data
Dla tych co mowia ze sie nie da - czasami sie da wyciagnac typ z generica, ale trzeba troche magii:
abstract class Super<T> {
final Class<?> clazz;
Super() {
clazz = (Class<?>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
void blah() {
System.out.println(clazz);
}
}
class SubA extends Super<Integer> {}
class SubB extends Super<String> {}
class SubC extends Super<Main> {}
public class Main {
public static void main(String[] args) {
new SubA().blah();
new SubB().blah();
new SubC().blah();
}
}
Czasami sie uzywa tego do robienia wlasnie generic dao i podklas, bez potrzeby powtarzania dla jakiego typu dane dao jest tworzone. To dziala tylko i wylacznie w konkretnych podklasach klasy generycznej ktore definiuja parametry. Np. class Sub<T> extends Super<T> nie zadziala (wywali sie w runtime).
@niezdecydowany - nie, on napisal ze trzeba miec gdzies pole typu T, nie napisal jak to zrobic. Ja mam pole typu Class<T> ktore automatycznie jest wyciagane w runtime i nie wymaga czegos takiego jak:
class Super<T> {
Class<T> clazz;
Super(Class<T> clazz) {
this.clazz = clazz;
}
}
class SubA extends Super<Integer> {
SubA() {
super(Integer.class); // powtarzanie sie
}
}
Z innej beczki: nigdzie nie napisalem ze jestem kozak, ja tylko napisalem ze cos sie da i podalem przyklad ktory dziala i pokazuje nie az tak do konca znane mozliwosci refleksji, za co zostalem zaatakowany. Skad ta agresja?
Mógłbyś chociaż czytać już udzielone odpowiedzi zamiast kopiować ...
A i @niezdecydowany mógłbyś podać alternatywę?
Misiaczki o co wy się kłócicie? Pomysł podany przez @the real mućka jest jak najbardziej OK i jest czymś innym niż to o czym wspominałem. Jednocześnie nie jest idealnym rozwiązaniem bo niekoniecznie zadziała dokładnie tak jakbyśmy chcieli (o czym zresztą autor sam wspomniał).
@Świetny Mleczarz jeśli nie chcesz robić osobnego DAO dla każdej podklasy (tzn technicznie rzecz biorąc to byłyby klasy na 1 linijkę kodu bo tylko coś w stylu CośtamDao extends GenericDao<Cośtam>
ale jednak ;) ) to będziesz musiał się pobawić w refleksje, innej drogi nie ma.
@pomidor: w tym czasie jak ty podales linka to ja pisalem przyklad i nie odswiezylem stronki. Bardzo przepraszam za blad. Nie powiesz jednak, ze wklejony kod jest lepszy niz jakas linijka zakopana gdzies w jakims artykule? Na SO tak sie pisze odpowiedzi, artykul pod linkiem moze zniknac...
@niezdecydowany: widze, ze jednak nie rozumiesz. Wg. ciebie robienei String klasa = "Integer" (swoja droga zle, musi byc java.lang.Integer) w SubA, oraz String klasa = "java.lang.String" w SubB, i taka linijka (statycznie napisana) w kazdej subklasie jest rownoznaczna z wyciaganiem typu raz, w jednym miejscu w klasie bazowej, dynamicznie?
Shalom napisał(a):
jeśli nie chcesz robić osobnego DAO dla każdej podklasy (tzn technicznie rzecz biorąc to byłyby klasy na 1 linijkę kodu bo tylko coś w stylu
CośtamDao extends GenericDao<Cośtam>
ale jednak ;) ) to będziesz musiał się pobawić w refleksje, innej drogi nie ma.
Mozna jeszcze zrobic jedno DAO i metody parametryzowac z przekazywaniem klasy:
class DAO {
<T> List<T> getAll(Class<T> clazz, A a, B b) { ... }
}
I tak dla kazdej metody. To sie nazywa runtime type token, opisane lepiej tutaj: https://docs.oracle.com/javase/tutorial/extra/generics/literals.html.
Nadal malo idealne rozwiazanie, ale moze moze...
@Mucka spoko
A co do dyskusji, to fajnie jeśli ktoś ma inne zdanie to niech chociaż poda jak to zrobić w inny sposób, a nie takie twierdzenie że czerwony golf jest szybszy bo czerwony
Dyskusje prowadzisz Ty, Shalom i ja, pozostali osobnicy trolluja: wywyzaja, obrazaja, uzywaja zwrotow typu 'ssie palke', co za dyskusje nie uwazam.