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
来说,这已经足够了;这似乎是一个例子,他们可以挽救我们一个沮丧。
必须返回Class
对象,没有其他方法
为什么?谁知道呢,也许是一些理想主义的偏见。如果它返回Class
,这将是Class
在新的Type
接口中的唯一出现。
真正的问题是Class
和Type
的混合。以前,所有类型都在Class
中表示。虽然已经很乱了,但还是可以忍受的。没有很多类型。
对于新的泛型类型,他们应该设计一个独立于Class
的更清晰和符合规范的Type
层次结构。相反,他们把Class
和Type
合并在一起,制造了更多的混乱。整个等级制度都说不通。任何不熟悉这门学科、不了解历史的人都会对这种无稽之谈感到震惊。
我不会对Type
的设计有很高的要求。例如,ParameterizedType
定义了equals()
,但没有定义hashCode()
。没有办法让ParameterizedType
的两个实现在一个哈希映射中工作。通配符也是一种类型?没有地狱。
方法的名字getRawType()
简直太蠢了。这与raw type
无关。它应该被简单地命名为getClassOrInterface()
。会不会太啰嗦?看看getActualTypeArguments()
吧。(是的,它返回实际的参数!不是假的!)
我一直在想这件事,我有一种预感。也许他们想为未来的疯狂留下可能:
public class Z<L extends List<?>> {
L<Double> test;
}
这不是合法的Java代码,但我认为它的意思很清楚;new Z<ArrayList<?>>().test
的类型为ArrayList<Double>
。
如果这是合法的,((ParameterizedType) test.getGenericType()).getRawType()
将返回一个TypeVariable
.
Sun对ParameterizedType
的实现定义了getRawType()
方法来返回Class<?>
。显然它只返回Class<?>
然而,在我的类路径中有更多的ParameterizedType
实现——从hibernate-validator,从aspectj, hibernate-annotations, jaxb。有些返回Class<?>
,有些返回Type
。我不知道怎么用
除了反射api之外,Type接口层次结构还有其他用途。例如,代码生成库可以定义自定义实现。JDK 8本身有三种不同的WildcardType实现。如果ParameterizedType.getRawType()返回一个Class实例,那么您需要能够随时创建一个Class实例。
Class是一种在jvm中非常根深蒂固的类型,它具有回本机管理内存的绑定。要创建Class实例,必须拥有定义类的字节码。但是在代码生成库的情况下,字节码甚至还不存在。如果他们要求ParameterizedType返回一个Class,它将限制Type接口层次结构的适用性,使其仅适用于反射api。这看起来可能没什么大不了的,但cast也不是什么大事。
ParameterizedType. getownertype()返回一个Type,因为它本身可能是一个Class或另一个ParameterizedType。理论上它可以返回一个TypeVariable,因为下面是有效的Java:
<M extends Map<?,?>> M.Entry<?,?> first(M map) { ... }
然而,它被编译为对类型变量擦除的静态引用,在这种情况下,M.Entry将被编译为Map.Entry。至少根据我的测试,从反射api调用getOwnerType()将是一个Class,而不是TypeVariable。