繁体   English   中英

Java中的通用方法参数的getClass()

[英]getClass() of a Generic Method Parameter in a Java

以下Java方法无法编译:

<T extends Number> void foo(T t)
{
    Class<? extends T> klass = t.getClass();
}

收到的错误是:类型不匹配:无法转换为Class<capture#3-of ? extends Number> Class<capture#3-of ? extends Number>Class<? extends T> Class<? extends T>

有人可以解释为什么Class<? extends T> Class<? extends T>无效,但Class<? extends Number> Class<? extends Number>

Javadoc说:

实际的结果类型是Class<? extends |X|> Class<? extends |X|> where | X | 是调用getClass的表达式的静态类型的擦除。 例如,此代码片段中不需要强制转换:

Number n = 0;
Class<? extends Number> c = n.getClass(); 

因为T类'类型不会从T延伸。 相反,它从Number扩展,正如您在<T extends Number> 就那么简单。

一个更好的问题是:

以下为什么不编译?

 <T extends Number> void foo(T t) { Class<T> class1 = t.getClass(); } 

答案是Object#getClass()返回带有无界通配符的Class<?> ? 因为对象本身并不直接了解其在任意方法中所期望的泛型类型。

这有点傻。 对于大多数用例,如果x.getClass()返回Class<? extends X> Class<? extends X> ,而不是擦除的Class<? extends |X|> Class<? extends |X|>

擦除是导致信息丢失的原因,使您的代码显然是安全的,无法编译。 t.getClass()返回Class<? extends |T|> Class<? extends |T|>|T| = Number |T| = Number ,所以返回Class<? extends Number> Class<? extends Number>

擦除(由语言规范强制要求)是为了保持理论上的正确性。 例如

List<String> x = ...;
Class<List> c1 = x.getClass(); // ok
Class<List<String>> c2 = x.getClass(); // error

虽然c2看起来很合理,但在Java中, List<String>实际上没有这样的类。 List只有一个类。 所以允许c2在理论上是不正确的。

这种形式在现实世界的用法中产生了很多问题,程序员可以推断出Class<? extends X> Class<? extends X>对于他们的目的是安全的,但必须处理已删除的版本。

您可以简单地定义自己的getClass ,返回未擦除的类型

static public <X> Class<? extends X> getFullClass(X x)
    return (Class<? extends X>)(Class) x.getClass() ;

<T extends Number> void foo(T t)
{
    Class<? extends T> klass = getFullClass(t);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM