671 Stimmen

Generischen Typ einer Klasse zur Laufzeit abrufen

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.

12voto

DaBlick Punkte 838

Ich denke, es gibt eine andere elegante Lösung.

Was Sie tun möchten, ist, den Typ des generischen Typparameters (sicher) von der konkurrierenden Klasse an die Oberklasse zu übergeben.

Wenn man sich erlaubt, den Klassentyp als "Metadaten" über die Klasse zu betrachten, legt dies die Java-Methode zur Kodierung von Metadaten zur Laufzeit nahe: Annotationen.

Definieren Sie zunächst eine benutzerdefinierte Bemerkung nach diesem Muster:

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EntityAnnotation {
    Class entityClass();
}

Sie müssen dann die Anmerkung zu Ihrer Unterklasse hinzufügen.

@EntityAnnotation(entityClass =  PassedGenericType.class)
public class Subclass<PassedGenericType> {...}

Dann können Sie diesen Code verwenden, um den Klassentyp in Ihrer Basisklasse zu erhalten:

import org.springframework.core.annotation.AnnotationUtils;
.
.
.

private Class getGenericParameterType() {
    final Class aClass = this.getClass();
    EntityAnnotation ne = 
         AnnotationUtils.findAnnotation(aClass, EntityAnnotation.class);

    return ne.entityClass();
}

Einige Einschränkungen dieses Ansatzes sind:

  1. Sie geben den generischen Typ ( PassedGenericType ) an ZWEI Stellen und nicht an einer, die nicht trocken ist.
  2. Dies ist nur möglich, wenn Sie die konkreten Unterklassen ändern können.

8voto

PJWeisberg Punkte 124

Hier ist eine Möglichkeit, die ich schon ein- oder zweimal anwenden musste:

public abstract class GenericClass<T>{
    public abstract Class<T> getMyType();
}

Zusammen mit

public class SpecificClass extends GenericClass<String>{

    @Override
    public Class<String> getMyType(){
        return String.class;
    }
}

7voto

Matthias M Punkte 10330

Das ist meine Lösung:

import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

public class GenericClass<T extends String> {

  public static void main(String[] args) {
     for (TypeVariable typeParam : GenericClass.class.getTypeParameters()) {
      System.out.println(typeParam.getName());
      for (Type bound : typeParam.getBounds()) {
         System.out.println(bound);
      }
    }
  }
}

6voto

Yaroslav Kovbas Punkte 380

Hier ist eine funktionierende Lösung!!!

@SuppressWarnings("unchecked")
    private Class<T> getGenericTypeClass() {
        try {
            String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
            Class<?> clazz = Class.forName(className);
            return (Class<T>) clazz;
        } catch (Exception e) {
            throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
        }
    } 

ANMERKUNGEN: Kann nur als Superklasse verwendet werden
1. Muss um eine typisierte Klasse erweitert werden ( Child extends Generic<Integer> )
OR

2. Muss als anonyme Implementierung erstellt werden ( new Generic<Integer>() {}; )

5voto

Paul92 Punkte 127

Eine einfache Lösung für diese Kabine sieht folgendermaßen aus

public class GenericDemo<T>{
    private T type;

    GenericDemo(T t)
    {
        this.type = t;
    }

    public String getType()
    {
        return this.type.getClass().getName();
    }

    public static void main(String[] args)
    {
        GenericDemo<Integer> obj = new  GenericDemo<Integer>(5);
        System.out.println("Type: "+ obj.getType());
    }
}

CodeJaeger.com

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.

Powered by:

X