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

如何使用反射和Guava TypeToken实例化参数化类的类对象

梁丘兴腾
2023-03-14

我正试图为一个使用泛型类型参数进行参数化的类施展一些Guava TypeToken魔法,但是当我试图通过< code > class . forname(String)方法实例化它时,却得到一个< code > ClassNotFoundException 。

public class EnumeratedMenu<E extends Enum<E>,T extends EnumeratedBean<E>> {

    private final TypeToken<EnumeratedMenu<E,T>> typeToken =
            new TypeToken<EnumeratedMenu<E,T>>(getClass()) { };

    private Class<T> getBean() {

        TypeToken<?> genericBeanParam = typeToken.resolveType(EnumeratedMenu.class.getTypeParameters()[1]);

        try {
            //This generates a ClassNotFoundException because of the generic type parameter that EnumeratedBean has.
            return (Class<T>)Class.forName(genericBeanParam.getType().getTypeName());
        } catch(ClassNotFoundException e) {
            log.error("Unable to find the class definition for {}", genericBeanParam.getType().getTypeName());
            log.catching(e);
        }
    }
}

我得到这个例外:

"无法找到EnumatedBean的类定义

ContextMenuOption$ContextTypeEnumeratedBean 的泛型 enum 参数的运行时类型。如何获取所需的类对象?

澄清:

我需要构造一个类的实例,以便与一个生成器对象一起使用,该对象将构造一个菜单选项,如下所示:

T optionBean = beanFactory.create(beanClass);

IEnumeratedMenuOptionBuilder<E,T> builder = new EnumeratedMenuOptionBuilder<>(optionBean);
builder.setDriver(getDriver()).setTimeoutInSeconds(getTimeoutInSeconds())
        .setEnumerationFunction(getEnumerationFunction());

共有2个答案

鲜于喜
2023-03-14
匿名用户

这是不可能的,因为不管参数化如何,总是只有一个<code>类。这就是Java泛型处理类型擦除的方式。有关如何和为什么的详细解释,您可能需要阅读:

http://www . angeli kalanger . com/generics FAQ/FAQ sections/technical details . html

但是对于实例化,你只需要使用你已经拥有的;并按所需方式强制转换泛型类型签名。

例如,这意味着您可以实际执行以下操作:

List<String> strings = new ArrayList<String>();
List<Integer> numbers = (List<Integer>)(List<?>) strings;
numbers.add(Integer.valueOf(12));

没有运行时异常。没有真正的运行时信息限制内容;只有隐式铸造。但是,如果您尝试以下操作,将会得到运行时异常:

String str = strings.get(0);

因为尽管底层<code>列表

因此,实例化的工作方式可能如下:

List<String> s = (List<String>) ArrayList.class.newInstance();

但是使用任何你想要的泛型类型。

编辑:

如果需要Guava的< code>TypeToken,它的javadocs建议您要么使用< code>getRawType()获取原始类,要么使用< code>constructor()直接创建实例。

经福
2023-03-14

你到底想在这里做什么?

你永远也上不了

可能有其他方法可以实现您想要的结果,但不清楚您当前想要的结果是什么。例如,您想使用要返回的Class来做什么?也许可以在没有中间Class对象的情况下做到这一点。

编辑:

由于看起来你想要的是能够创建一个T实例,所以这里有一个如何使用TypeToken做到这一点的示例:

public class EnumeratedMenu<E extends Enum<E>, T extends EnumeratedBean<E>> {

  // Just get the type of T, that's what we care about here
  private final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {};

  private T create() {
    try {
      // Using the raw type Class object for the token to
      // get at its default constructor.
      return typeToken.constructor(typeToken.getRawType().getConstructor())
          .invoke(null);
    } catch (Exception e) {
      // ...
    }
  }
}

 类似资料:
  • 问题内容: 是否可以使用Java反射从另一个类实例化私有内部类。例如,如果我采用了这段代码 是否可以实例化并从main类中的main方法获得对Test的访问。 问题答案: 使用反射时,您会发现该内部类的构造函数将外部类的实例作为附加参数(总是第一个)。 例:

  • 是否可以从类main中的main方法实例化并获得对Test的访问。

  • 问题内容: 如何使用反射在Java中创建通用的参数化类? 我有 我需要一个实例。 我尝试了 但找不到可以让我获取适当​​类型的实例的语法,例如说 那么,我该怎么做呢? 问题答案: Java使用基于擦除的仿制药(即,类型参数是在运行时,例如擦除,并且被视为在运行时是同一类型)。由于反射本质上是运行时功能,因此根本不使用或不涉及类型参数。 换句话说,当您使用反射时,您只能实例化原始类型(,不能实例化)

  • 我尝试实例化以下Java代码中定义的内部类: 我得到了这个例外: 我错过了什么?

  • 问题内容: 我正在使用reflect.MakeFunc编写函数。该函数可以返回错误。成功时,我希望它为错误类型的返回值返回nil。我该如何使用反射?目前我有这个: 我懂了。我也尝试添加一个之后,但我得到了。我尝试了,但出现了细分错误。 如何获得代表nil错误的reflect.Value? 问题答案: 使用以下内容: 让我们分解一下。第一步是为: 。更简单的方法不起作用,因为参数的具体值为。没有类型

  • 我不能创建B-Object,但为什么呢? 例外情况是: