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
原样合作是足够的捶打;这似乎是一个他们可以为我们拯救一个沮丧的实例。
答案 0 :(得分:13)
它必须返回一个Class
对象,没有别的办法。
为什么呢?谁知道,也许是一些理想主义的偏见。如果它返回Class
,则它将是新Class
接口中Type
的唯一外观。
真正的问题是Class
和Type
的混合。以前,所有类型都在Class
中表示。它已经很乱了,但仍然可以容忍。种类不多。
使用新的通用类型,他们应该设计一个独立于Type
的更清晰且符合规范的Class
层次结构。相反,他们将Class
与Type
合并,造成更多混乱。整个层次结构都没有意义。任何对该主题不熟悉并且不了解历史的人都会被这种废话吓到。
我不会将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()将是一个类,至少根据我的测试。