如何获得泛型类型t的类示例?

lokaqttq  于 2021-07-14  发布在  Java
关注(0)|答案(22)|浏览(748)

我有个泛型课, Foo<T> . 以一种 Foo ,我要获取类型的类示例 T ,但我就是打不来 T.class .
用什么方法绕过它 T.class ?

9bfwbjaz

9bfwbjaz1#

我假设,既然你有一个泛型类,你会有这样一个变量:

private T t;

(此变量需要在构造函数处取一个值)
在这种情况下,您只需创建以下方法:

Class<T> getClassOfInstance()
{
    return (Class<T>) t.getClass();
}

希望有帮助!

xa9qqrwz

xa9qqrwz2#

我正在为此使用变通方法:

class MyClass extends Foo<T> {
....
}

MyClass myClassInstance = MyClass.class.newInstance();
xghobddn

xghobddn3#

我想把t.class传递给一个使用泛型的方法
readfile方法通过fullpath读取由文件名指定的.csv文件。可以有不同内容的csv文件,因此我需要传递模型文件类,以便我可以得到适当的对象。因为这是读取csv文件,我想在一个通用的方式做。出于某种原因,上述解决方案对我都不起作用。我需要使用 Class<? extends T> type 让它工作。我使用opencsv库来解析csv文件。

private <T>List<T> readFile(String fileName, Class<? extends T> type) {

    List<T> dataList = new ArrayList<T>();
    try {
        File file = new File(fileName);

        Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
        Reader headerReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));

        CSVReader csvReader = new CSVReader(headerReader);
        // create csv bean reader
        CsvToBean<T> csvToBean = new CsvToBeanBuilder(reader)
                .withType(type)
                .withIgnoreLeadingWhiteSpace(true)
                .build();

        dataList = csvToBean.parse();
    }
    catch (Exception ex) {
        logger.error("Error: ", ex);
    }

    return dataList;
}

这就是readfile方法的调用方式

List<RigSurfaceCSV> rigSurfaceCSVDataList = readSurfaceFile(surfaceFileName, RigSurfaceCSV.class);
scyqe7ek

scyqe7ek4#

这个问题由来已久,但现在最好的是使用谷歌 Gson .
获取自定义的示例 viewModel .

Class<CustomViewModel<String>> clazz = new GenericClass<CustomViewModel<String>>().getRawType();
CustomViewModel<String> viewModel = viewModelProvider.get(clazz);

泛型类型类

class GenericClass<T>(private val rawType: Class<*>) {

    constructor():this(`$Gson$Types`.getRawType(object : TypeToken<T>() {}.getType()))

    fun getRawType(): Class<T> {
        return rawType as Class<T>
    }
}
zlwx9yxi

zlwx9yxi5#

实际上,我想你的类中有一个类型为t的字段。如果没有类型为t的字段,那么拥有泛型类型又有什么意义呢?所以,你可以在这个字段上做一个instanceof。
就我而言,我有一个

List<T> items;

在我的类中,我通过

if (items.get(0) instanceof Locality) ...

当然,这只有在可能的类的总数有限的情况下才有效。

aiazj4mn

aiazj4mn6#

很多人不知道这个把戏!其实,我今天才找到的!就像做梦一样!看看这个例子:

public static void main(String[] args) {
    Date d=new Date();  //Or anything you want!
    printMethods(d);
}

public static <T> void printMethods(T t){
    Class<T> clazz= (Class<T>) t.getClass(); // There you go!
    for ( Method m : clazz.getMethods()){
        System.out.println( m.getName() );
    }
}
gk7wooem

gk7wooem7#

如果要扩展或实现任何使用泛型的类/接口,则可以获得父类/接口的泛型类型,而无需修改任何现有的类/接口。
可能有三种可能性,
案例1当您的类扩展一个使用泛型的类时

public class TestGenerics {
    public static void main(String[] args) {
        Type type = TestMySuperGenericType.class.getGenericSuperclass();
        Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
        for(Type gType : gTypes){
            System.out.println("Generic type:"+gType.toString());
        }
    }
}

class GenericClass<T> {
    public void print(T obj){};
}

class TestMySuperGenericType extends GenericClass<Integer> {
}

案例2当类实现一个使用泛型的接口时

public class TestGenerics {
    public static void main(String[] args) {
        Type[] interfaces = TestMySuperGenericType.class.getGenericInterfaces();
        for(Type type : interfaces){
            Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
            for(Type gType : gTypes){
                System.out.println("Generic type:"+gType.toString());
            }
        }
    }
}

interface GenericClass<T> {
    public void print(T obj);
}

class TestMySuperGenericType implements GenericClass<Integer> {
    public void print(Integer obj){}
}

案例3:当您的接口正在扩展使用泛型的接口时

public class TestGenerics {
    public static void main(String[] args) {
        Type[] interfaces = TestMySuperGenericType.class.getGenericInterfaces();
        for(Type type : interfaces){
            Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
            for(Type gType : gTypes){
                System.out.println("Generic type:"+gType.toString());
            }
        }
    }
}

interface GenericClass<T> {
    public void print(T obj);
}

interface TestMySuperGenericType extends GenericClass<Integer> {
}
z0qdvdin

z0qdvdin8#

public <T> T yourMethodSignature(Class<T> type) {

        // get some object and check the type match the given type
        Object result = ...            

        if (type.isAssignableFrom(result.getClass())) {
            return (T)result;
        } else {
            // handle the error
        }
   }
u2nhd7ah

u2nhd7ah9#

这很直截了当。如果您需要来自同一班级:

Class clazz = this.getClass();
ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
try {
        Class typeClass = Class.forName( parameterizedType.getActualTypeArguments()[0].getTypeName() );
        // You have the instance of type 'T' in typeClass variable

        System.out.println( "Class instance name: "+  typeClass.getName() );
    } catch (ClassNotFoundException e) {
        System.out.println( "ClassNotFound!! Something wrong! "+ e.getMessage() );
    }
jjhzyzn0

jjhzyzn010#

如其他答案所述,使用 ParameterizedType 方法,您需要扩展类,但这似乎是额外的工作,使一个全新的类扩展它。。。
因此,使类抽象化会迫使您对其进行扩展,从而满足子类化需求(使用lombok的@getter)。

@Getter
public abstract class ConfigurationDefinition<T> {

    private Class<T> type;
    ...

    public ConfigurationDefinition(...) {
        this.type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        ...
    }
}

现在不需要定义新类就可以扩展它(注意结尾的{}。。。扩展,但不要覆盖任何内容(除非您愿意)。

private ConfigurationDefinition<String> myConfigA = new ConfigurationDefinition<String>(...){};
private ConfigurationDefinition<File> myConfigB = new ConfigurationDefinition<File>(...){};
...
Class stringType = myConfigA.getType();
Class fileType = myConfigB.getType();
idfiyjo8

idfiyjo811#

我找到了一个通用而简单的方法。在我的类中,我创建了一个方法,该方法根据泛型类型在类定义中的位置返回泛型类型。假设类定义如下:

public class MyClass<A, B, C> {

}

现在,让我们创建一些属性来持久化这些类型:

public class MyClass<A, B, C> {

    private Class<A> aType;

    private Class<B> bType;

    private Class<C> cType;

// Getters and setters (not necessary if you are going to use them internally)

    }

然后可以创建一个泛型方法,该方法基于泛型定义的索引返回类型:

/**
     * Returns a {@link Type} object to identify generic types
     * @return type
     */
    private Type getGenericClassType(int index) {
        // To make it use generics without supplying the class type
        Type type = getClass().getGenericSuperclass();

        while (!(type instanceof ParameterizedType)) {
            if (type instanceof ParameterizedType) {
                type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
            } else {
                type = ((Class<?>) type).getGenericSuperclass();
            }
        }

        return ((ParameterizedType) type).getActualTypeArguments()[index];
    }

最后,在构造函数中,只需调用方法并发送每个类型的索引。完整的代码应该如下所示:

public class MyClass<A, B, C> {

    private Class<A> aType;

    private Class<B> bType;

    private Class<C> cType;

    public MyClass() {
      this.aType = (Class<A>) getGenericClassType(0);
      this.bType = (Class<B>) getGenericClassType(1);
      this.cType = (Class<C>) getGenericClassType(2);
    }

   /**
     * Returns a {@link Type} object to identify generic types
     * @return type
     */
    private Type getGenericClassType(int index) {

        Type type = getClass().getGenericSuperclass();

        while (!(type instanceof ParameterizedType)) {
            if (type instanceof ParameterizedType) {
                type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
            } else {
                type = ((Class<?>) type).getGenericSuperclass();
            }
        }

        return ((ParameterizedType) type).getActualTypeArguments()[index];
    }
}
fjnneemd

fjnneemd12#

简单的回答是,在java中找不到泛型类型参数的运行时类型。我建议阅读java教程中有关类型擦除的一章以了解更多细节。
一个流行的解决办法是通过 Class 将类型参数的。

class Foo<T> {
    final Class<T> typeParameterClass;

    public Foo(Class<T> typeParameterClass) {
        this.typeParameterClass = typeParameterClass;
    }

    public void bar() {
        // you can access the typeParameterClass here and do whatever you like
    }
}
5sxhfpxr

5sxhfpxr13#

有可能:

class Foo<T> {
  Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(Foo.class, this.getClass()).get(0);
}

您需要两个来自hibernate generic dao/blob/master/dao/src/main/java/com/googlecode/genericdao/dao/daoutil.java的函数。
有关更多解释,请参见反射泛型。

xeufq47z

xeufq47z14#

对于这个问题,我有一个(丑陋但有效的)解决方案,它不需要外部依赖项/库:

import java.lang.reflect.TypeVariable;

public static <T> Class<T> getGenericClass() {
    __<T> instance = new __<T>();
    TypeVariable<?>[] parameters = instance.getClass().getTypeParameters(); 

    return (Class<T>)parameters[0].getClass();
}

// Generic helper class which (only) provides type information. This avoids the usage
// of a local variable of type T, which would have to be initialized.
private final class __<T> {
    private __() {
    }
}
pobjuy32

pobjuy3215#

一个比其他人建议的类更好的方法是传入一个对象,这个对象可以执行您对该类所做的操作,例如,创建一个新示例。

interface Factory<T> {
  T apply();
}

<T> void List<T> make10(Factory<T> factory) {
  List<T> result = new ArrayList<T>();
  for (int a = 0; a < 10; a++)
    result.add(factory.apply());
  return result;
}

class FooFactory<T> implements Factory<Foo<T>> {
  public Foo<T> apply() {
    return new Foo<T>();
  }
}

List<Foo<Integer>> foos = make10(new FooFactory<Integer>());

相关问题