当前位置: 首页 > 知识库问答 >
问题:

泛型Java-获取泛型的泛型类型

姜德容
2023-03-14

如何获取这个类的类型?对于上下文,我使用ModelMapper,我需要类类型T从S转换为T。

@Component
public class A<T, S> {
    
    private Class<T> tType;
    private Class<S> sType;
    
    @SuppressWarnings("unchecked")
    public A() {
        this.tType = (Class<T>) // some method to take the type
        this.sType = (Class<S>) // some method to take the type
    }   

    public T toModel(S regras) {
        return modelMapper.map(regras, tType); 
    }

背景:

public class B{

    @Autowired 
    private A<SomeClassX, SomeClassY> var;
    
    // Some code

我已经尝试了N种方法,其中我放置了“//一些方法来获取类型”,但没有任何效果。例如:

    @SuppressWarnings("unchecked")
    public A() {
        this.tType = (Class<T>) getGenericClassType(0);
        this.sType = (Class<S>) getGenericClassType(1);
    }   

    private Type getGenericClassType(int index) {
        Type type = getClass().getGenericSuperclass(); 
        while(!(type instanceof ParameterizedType)) { 
            if (type == null) { 
                return null; 
            }
            
            if (type instanceof ParameterizedType) {
                type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
            } else {
                type = ((Class<?>) type).getGenericSuperclass();
            } 
        }
        
        return ((ParameterizedType) type).getActualTypeArguments()[index];
    }

    @SuppressWarnings("unchecked")
    public A() {
        this.tType = (Class<T>) GenericTypeResolver.resolveTypeArguments(getClass(), GenericConverter.class)[0];
        this.sType = (Class<S>) GenericTypeResolver.resolveTypeArguments(getClass(), GenericConverter.class)[1];
    }   

共有1个答案

邓德厚
2023-03-14

你不能。泛型是编译器想象出来的:编译器使用泛型生成错误和注入类型转换,然后将其全部删除。它不在类文件中,因此在运行时不可用,因此,“我的t实际上是什么”的概念是不可能的。

有一些变通方法:

当然,您可以将一个j.l.Class实例传递给构造函数。您的代码片段使用了“A”和“B”这两个名称,这非常不幸,因为单大写通常用于类型vars,所以我将把它们命名为mycopa和MyCombB。

像这样的东西:

public class MyCompA<S, T> {
  private final Class<S> sourceType;
  private final Class<T> targetType;

  public MyCompA(Class<S> sourceType, Class<T> targetType) {
    this.sourceType = sourceType;
    this.targetType = targetType;
  }

  public T toModel(S regras) {
      return modelMapper.map(regras, targetType); 
  }
}

尽管如此,听起来您实际上并不需要任何源类型,所以您最好不要使用它。

这种策略有两个问题:

  • 有一些东西是泛型无法表示的,一个j.l.Class实例可以表示这些东西。具体来说,原语:int,原语有一个表示它的j.l.Class实例;您可以使用表达式int.class获得它int是无效的泛型(至少还没有,可能在将来的java版本中):Class

一种方法是STT。它们看起来很时髦。制作它们:

TypeToken<List<String>> = new TypeToken<>() {};

注意这里奇怪的尾随符。这将创建一个匿名类,而类确实携带泛型信息,这些信息在编译后仍然存在,因此可以通过反射访问进行查询。运行时系统对它没有任何作用——就JVM而言,它是注释(JVM不知道泛型是什么,也不把它们用于任何事情。它位于类文件中,仅用于javac,但我们可以通过反射来读取它,就是这样)。

public abstract class TypeToken<T> {
  public Type getType() {
    Type t = getClass().getGenericSuperclass();
    if (!(t instanceof ParameterizedType pt)) throw new IllegalStateException("Incorrect use of TypeToken: " + t);
    
    Type[] typeArgs = pt.getActualTypeArguments();
    if (typeArgs.length == 1) return typeArgs;
    throw new IllegalStateException("Incorrect use of TypeToken: " + t);
}

我已经向您展示了如何创建这些实例。如果您愿意,您可以在构造函数中包含对getType()调用(您可能想要缓存返回值;它不能更改并且反射可能有点昂贵),因为这样您将在创建无效类型标记时获得异常(例如:new TypeToken() {}-这是原始用法,当然在这里不起作用,重点是捕获中的内容

显然,您的ModelMapper.map方法需要Class类型的值

 类似资料:
  • 问题内容: 我有一个列表,程序是这样的:。有什么方法可以使用T变量获取类的名称(因此我可以从内部知道T是否为String,Socket等)? 编辑:没关系,在这里找到了答案。 问题答案: 简短答案 :您不能。 长答案 : 由于使用Java实现泛型的方式,泛型T在运行时不会保留。您仍然可以使用私有数据成员: 用法示例:

  • 问题内容: 我在使用泛型时遇到麻烦。给出以下示例: 什么 ???应该 ? 不工作… 也不。 不工作… 如果有Java泛型专家,我需要帮助…:/ 问题答案: 由于类型擦除,您可能无法获得除外。你将不得不使用不安全的类型转换投下的-具体而言,将做的工作。

  • 问题内容: 背景 我曾经写过这种方法: 应该这样称呼它: 这很好用(尽管我在研究当前容易出错的问题时在这里的答案中已经看到)。 目前的情况 无论如何,现在我正在编写以下代码(在扩展javax.servlet.jsp.tagext.TagSupport的类中): 目的是可以这样称呼: 我的评估方法中的代码显然不起作用。的第二个参数应该是Class对象。这导致我: 我的问题 如何获得通用(返回)类型的

  • 问题内容: 我有一个代表文本片段的泛型类。该文本片段可能具有多种不同模式(突出显示的不同类型)中的任何一种。这些模式用枚举表示。每个项目的Enum可能不同,但是它必须实现一个接口,该接口提供了一种将其中两个结合的方法(可以突出显示并加粗显示)。所以我有一个界面: 然后我的TextFragment是文本字符串和模式的容器。但是当我尝试声明该类时: 我收到以下错误: 令牌“扩展”的语法错误,预期 根据

  • 问题内容: 如果在Java中创建泛型类(该类具有泛型类型参数),则可以使用泛型方法(该方法带有泛型类型参数)吗? 考虑以下示例: 正如您对通用方法所期望的那样,我可以使用任何对象调用的实例: 但是,如果我尝试使用 不 指定泛型类型的实例,则无论传入什么,我都会调用返回, 奇怪的是,如果返回类型是通用类,它将编译(例如(实际上,这可以解释-参见下面的答案)): 此外,如果输入通用类,即使仅使用通配符

  • 如果在Java中创建泛型类(该类具有泛型类型参数),是否可以使用泛型方法(该方法采用泛型类型参数)? 考虑下面的例子: 正如您所期望的那样,对于任何对象,的实例,我都可以调用: 但是,如果我试图使用的实例而不指定泛型类型,那么调用将返回一个