ParameterizedType.getRawType()返回j.l.r.Type,而不是Class <! - ? - >?

时间:2011-04-23 21:39:50

标签: java reflection

ParameterizedType parameterized =
    (ParameterizedType) List.class.getMethod("iterator").getGenericReturnType();
Type raw = parameterized.getRawType();

ParameterizedType#getRawType()返回Type,而不是Class<?>(虽然我得到java.lang.Class现在实现Type)。是否有充分理由说明getRawType()未将其返回类型声明为Class<?>?是否存在getRawType()的结果可能不是Class<?>的极端情况?

j.l.r.Type原样合作是足够的捶打;这似乎是一个他们可以为我们拯救一个沮丧的实例。

4 个答案:

答案 0 :(得分:13)

它必须返回一个Class对象,没有别的办法。

为什么呢?谁知道,也许是一些理想主义的偏见。如果它返回Class,则它将是新Class接口中Type的唯一外观。

真正的问题是ClassType的混合。以前,所有类型都在Class中表示。它已经很乱了,但仍然可以容忍。种类不多。

使用新的通用类型,他们应该设计一个独立于Type的更清晰且符合规范的Class层次结构。相反,他们将ClassType合并,造成更多混乱。整个层次结构都没有意义。任何对该主题不熟悉并且不了解历史的人都会被这种废话吓到。

我不会将Type的设计保持在高标准。例如,ParameterizedType定义equals(),但不定义hashCode()。没有办法让ParameterizedType的两个实现在一个哈希映射中工作。而通配符也是一种类型?没有。

方法getRawType()的名称只是愚蠢的。它与raw type无关。它应该明确地命名为getClassOrInterface()。会不会太冗长?那么看看getActualTypeArguments()。 (是的,它会返回实际的参数!不是假的!)

答案 1 :(得分:3)

Sun对ParameterizedType的实施已定义getRawType()方法返回Class<?>。所以它显然只返回Class<?>

但是,在我的类路径中还有一些ParameterizedType的实现 - 来自hibernate-validator,来自aspectj,hibernate-annotations,jaxb。其中一些返回Class<?>,一些返回Type。我不知道它们是如何使用的。

答案 2 :(得分:2)

我在想这个,我有预感。也许他们想要为这样的未来疯狂留下可能性:

public class Z<L extends List<?>> {
    L<Double> test;
}

这不是合法的Java代码,但我认为它的含义很清楚; new Z<ArrayList<?>>().test的类型为ArrayList<Double>

如果这是合法的,((ParameterizedType) test.getGenericType()).getRawType()将返回TypeVariable

答案 3 :(得分:1)

Type接口层次结构还有其他用途,而不仅仅是反射api。例如,代码生成库可以定义自定义实现。 JDK 8本身有3种不同的WildcardType实现。如果ParameterizedType.getRawType()返回了一个Class实例,那么您需要能够随时创建一个Class实例。

Class是一种非常根深蒂固的JVM类型,它具有绑定回本机管理的内存。要创建Class实例,必须具有定义类的字节代码。但是在代码生成库的情况下,字节代码甚至还不存在。如果他们需要ParameterizedType返回一个Class,它会将Type接口层次结构的适用性限制为仅反射api。

这可能看起来不是什么大问题,但也不是演员。

ParameterizedType.getOwnerType()返回一个Type,因为它本身可以是Class或另一个ParameterizedType。它理论上可以返回一个TypeVariable,因为以下是有效的Java:

<M extends Map<?,?>> M.Entry<?,?> first(M map) { ... }

但是,它被编译为类型变量擦除的静态引用,在这种情况下,M.Entry将被编译为Map.Entry。而不是TypeVariable,从反射api调用getOwnerType()将是一个类,至少根据我的测试。