当前位置: 首页 > 面试题库 >

使用反射在运行时推断Java泛型参数

马安邦
2023-03-14
问题内容

我有以下签名的方法:

// Converts a json string to a list of objects
// Assumption: json is an array, and all items in the list are of the same type
public <T> List<T> getListFromJson( String json, Class<T> itemType, List<T> defValue ) {
    final ArrayList<T> list = new ArrayList<T>();

    for( JsonElement e : parser.parse(json).getAsJsonArray())
        list.add( (T) (
                Number.class.isAssignableFrom(itemType) ? e.getAsNumber() :
                Boolean.class.isAssignableFrom(itemType) ? e.getAsBoolean() :
                Character.class.isAssignableFrom(itemType) ? e.getAsCharacter() :
                String.class.isAssignableFrom(itemType) ? e.getAsString() :
                JsonElement.class.isAssignableFrom(itemType) ? e :
                null
            )
        );

    return list;
}

它读取json字符串,并将其转换为适当类型的对象的列表,例如。整数,字符串

是否有一种可靠Class<T>的方法可以通过从List<T>参数中推断出参数来将其从方法中删除?例如。有没有办法可以在不丢失功能的情况下将方法签名更改为以下内容?

public <T> List<T> getListFromJson( String json, List<T> defValue ) {
    ...
}

似乎该解决方案将需要对ParameterizedType进行一些精美的操作。我看了以下内容,但是我使用的方法不正确,或者它们没有达到我的期望:

  • 来自http://www.artima.com/weblogs/viewpost.jsp?thread=208860的 getTypeArguments()
  • 来自https://code.google.com/p/aphillips/source/browse/commons-lang/trunk/src/main/java/com/qrmedia/commons/lang/ClassUtils.java的 getActualTypeArguments()

问题答案:

由于类型擦除,您绝对不能“推断”什么T-它甚至在运行时不存在。您可能最接近的是检查其中的值defValue(如果有值)并在那里获取元素的类。

Class<?> tType = defValue.get(0).getClass();

if (Boolean.class.isAssignableFrom(tType)) { //...

编辑

关于使用反射等的思考getTypeArguments(),这些仅提供 声明 类型的数据, 而不 提供 实际
类型的数据。因此,例如,如果您获得了该Method对象的句柄并调用getTypeParameters(),则只会得到一个包含类型对象的数组,该对象表示-
T而不是T表示某些特定运行时调用所代表的实际类型。



 类似资料:
  • 我需要 Kotlin 中的一个集合来仅包含实现给定接口的元素。 例如:包含动物集合的地图: 通过阅读文档、博客和SO问题,我编写了使用Generics in关键字的代码: 现在我想在Test类中添加一个读取“data”内容的方法,例如将其打印到控制台: 如果我这样做,我会遇到编译错误: 我的解决方案是强制我的动物进入一个ArrayList 但是我不确定这是编写这种代码的最好方式。有没有更好的方式告

  • 我在Java 8中试验新的lambda,我正在寻找一种方法,在lambda类上使用反射来获得lambda函数的返回类型。我对lambda实现通用超接口的情况特别感兴趣。在下面的代码示例中, 到泛型类型参数T。 即使对于本身是泛型的子类,如果已知其他一些泛型参数,也有某些方法可以找出与泛型参数绑定的内容。考虑下例中的情况2,IdentityMapper,其中F和T都绑定到同一类型。当我们知道时,如果

  • 问题内容: 我正在为核心数据编写通用包装类。 这是我的一些基本类型。没什么特别的。 我已经将我的coredata写在协议中抽象化了。如果您让我知道您对我要提出的抽象的意见,我将不胜感激。但是在扩展中,我遇到了以下错误: 无法将类型“ NSFetchRequest”的值转换为预期的参数类型“ NSFetchRequest <_>” 不确定我该如何解决。我尝试了各种更改代码的尝试,但未成功…… 另外,

  • 问题内容: 我读到从Java 7开始,像在第一条语句中那样在右侧指定类型来创建Collections是不好的样式,因为编译器可以从左侧推断类型。 我的问题是,当像这样初始化列表时,编译器找不到类型,并且我收到未经检查的类型警告: 问题答案: 编译器不会 推断 类型,因为您正在实例化 raw 。但是它足够聪明,可以警告您在使用此(原始)对象时可能会出现问题。 值得一提的是此警告背后的原因。由于类型擦

  • 下面的代码被认为是运行时反射还是类型内省? 我想在编译阶段使用它,不想在运行时使用任何资源(包括时间)。它是否使用任何运行时资源?