Wie kann ich das erreichen?
public class GenericClass<T>
{
public Type getMyType()
{
//How do I return the type of T?
}
}
Alles, was ich bisher versucht habe, ergibt immer den Typ Object
und nicht der verwendete Typ.
Wie kann ich das erreichen?
public class GenericClass<T>
{
public Type getMyType()
{
//How do I return the type of T?
}
}
Alles, was ich bisher versucht habe, ergibt immer den Typ Object
und nicht der verwendete Typ.
Ja, das können Sie.
Java kennt keine verwenden. die Informationen zur Laufzeit aus Gründen der Abwärtskompatibilität. Aber die Informationen sind tatsächlich vorhanden als Metadaten und kann über Reflexion aufgerufen werden (wird aber noch nicht für die Typüberprüfung verwendet).
Aus der offiziellen API:
Cependant Für Ihr Szenario würde ich keine Reflexion verwenden. Ich persönlich bin eher geneigt, dass für Framework-Code zu verwenden. In Ihrem Fall würde ich einfach den Typ als Konstruktor-Parameter hinzufügen.
Ich habe folgenden Ansatz gewählt:
public class A<T> {
protected Class<T> clazz;
public A() {
this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
public Class<T> getClazz() {
return clazz;
}
}
public class B extends A<C> {
/* ... */
public void anything() {
// here I may use getClazz();
}
}
Ich glaube nicht, dass Sie können, Java verwendet Typ Löschung beim Kompilieren, so dass Ihr Code mit Anwendungen und Bibliotheken, die vor Generika erstellt wurden kompatibel ist.
Aus den Oracle Docs:
Typ Löschung
Generics wurden in die Sprache Java eingeführt, um strengere Typprüfungen zur Kompilierungszeit und zur Unterstützung der generischen Programmierung. Um Generika zu implementieren, wendet der Java-Compiler Typlöschung an:
Ersetzen Sie alle Typparameter in generischen Typen durch ihre Begrenzungen oder Object, wenn die Typparameter nicht begrenzt sind. Der erzeugte Bytecode, enthält daher nur gewöhnliche Klassen, Schnittstellen und Methoden. Fügen Sie bei Bedarf Typ-Casts ein, um die Typsicherheit zu erhalten. Erzeugen Sie Brückenmethoden, um den Polymorphismus in erweiterten generischen Typen zu erhalten. Die Typlöschung stellt sicher, dass für parametrisierte Typen keine neuen Klassen erzeugt werden. Typen erstellt werden; folglich verursachen generische Typen keinen Laufzeit-Overhead.
http://docs.oracle.com/javase/tutorial/java/generics/erasure.html
Die in diesem Artikel beschriebene Technik Artikel von Ian Robertson funktioniert für mich.
Ein kurzes und knappes Beispiel:
public abstract class AbstractDAO<T extends EntityInterface, U extends QueryCriteria, V>
{
/**
* Method returns class implementing EntityInterface which was used in class
* extending AbstractDAO
*
* @return Class<T extends EntityInterface>
*/
public Class<T> returnedClass()
{
return (Class<T>) getTypeArguments(AbstractDAO.class, getClass()).get(0);
}
/**
* Get the underlying class for a type, or null if the type is a variable
* type.
*
* @param type the type
* @return the underlying class
*/
public static Class<?> getClass(Type type)
{
if (type instanceof Class) {
return (Class) type;
} else if (type instanceof ParameterizedType) {
return getClass(((ParameterizedType) type).getRawType());
} else if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
Class<?> componentClass = getClass(componentType);
if (componentClass != null) {
return Array.newInstance(componentClass, 0).getClass();
} else {
return null;
}
} else {
return null;
}
}
/**
* Get the actual type arguments a child class has used to extend a generic
* base class.
*
* @param baseClass the base class
* @param childClass the child class
* @return a list of the raw classes for the actual type arguments.
*/
public static <T> List<Class<?>> getTypeArguments(
Class<T> baseClass, Class<? extends T> childClass)
{
Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();
Type type = childClass;
// start walking up the inheritance hierarchy until we hit baseClass
while (!getClass(type).equals(baseClass)) {
if (type instanceof Class) {
// there is no useful information for us in raw types, so just keep going.
type = ((Class) type).getGenericSuperclass();
} else {
ParameterizedType parameterizedType = (ParameterizedType) type;
Class<?> rawType = (Class) parameterizedType.getRawType();
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
for (int i = 0; i < actualTypeArguments.length; i++) {
resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
}
if (!rawType.equals(baseClass)) {
type = rawType.getGenericSuperclass();
}
}
}
// finally, for each actual type argument provided to baseClass, determine (if possible)
// the raw class for that type argument.
Type[] actualTypeArguments;
if (type instanceof Class) {
actualTypeArguments = ((Class) type).getTypeParameters();
} else {
actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
}
List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
// resolve types by chasing down type variables.
for (Type baseType : actualTypeArguments) {
while (resolvedTypes.containsKey(baseType)) {
baseType = resolvedTypes.get(baseType);
}
typeArgumentsAsClasses.add(getClass(baseType));
}
return typeArgumentsAsClasses;
}
}
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.