如何在java中获取泛型类型类

问题描述 投票:0回答:2

我的课程如下

abstract class GenericAnimal<T> {
   
   public String doActionWithTheAnimal() {
     return "Performing action with " + getGenericTypeClass(); 
   }

   private Class<?> getGenericTypeClass() {...} // how to get the Generic Type class?

}

class ZooAnimal extends GenericAnimal<Bear> {}

class Bear {}

class Test {
   public static void main(String[] args) {
     
      ZooAnimal animal = new ZooAnimal();

      System.out.println(animal.doActionWithTheAnimal());

   }
}

注意:很抱歉故意设计这个示例来适合我的用例。

我在网上找到了一个解决方案,其工作原理如下

    private Class<?> getGenericTypeClass() {
       return (Class<T>) ((ParameterizedType) getClass()
            .getGenericSuperclass()).getActualTypeArguments()[0];
    } 

我能想到的避免这段代码的另一种方法是要求 doActionWithTheAnimal() 方法的调用者自行传递类类型。我觉得不应该这样做,因为还有其他方法可以获取类类型而不询问代码的调用者/用户。

有人可以展示一种更简单/更干净的方法来获取泛型类型吗?

java generics coding-style code-standards
2个回答
0
投票

我可以看到另外两个选项。一种是将泛型类型作为构造函数参数传递:

abstract class GenericAnimal<T> {
  private final Class<T> type;
  GenericAnimal(Class<T> type) {
    this.type = type
  }
}

第二种是使用Guava的

TypeToken
来捕获类型:

  abstract class GenericAnimal<T> {
     TypeToken<T> type = new TypeToken<T>(getClass()) {};
  }
  new GenericAnimal<String>() {}.type // String

这是否是一种改进,取决于你。您自己的解决方案也是完全可行的。事实上,我想

TypeToken
在内部做了类似的事情。


0
投票

有人可以展示一种更简单/更干净的方法来获取泛型类型吗?

不,没有比您概述的两种更好的方法了。

请注意,您描述的第二种方式(传递类)将您限制为

T
的非参数化值 - 例如,您无法创建
GenericAnimal<List<String>>
,因为不存在
List<String>.class
这样的东西。但是,您的第一种方法将允许这样的子类(除非您显式转换为
Class<T>
,这对于参数化
T
可能会失败)。

第一种方法并不是特别复杂或肮脏:它可以位于父类中,子类中不需要做任何其他事情就可以使用它。

© www.soinside.com 2019 - 2024. All rights reserved.