繁体   English   中英

Java 所需类型<t>假如<!--?-->通用编译错误</t>

[英]Java required type <T> provided <?> generic compilation error

Java 怎么无法解释这段代码:

    private <T> Class<T> getClass(T object) {
       return object.getClass();
    }

我试图想象这一点,当我代替一个例子时

    private Class<String> getClass(String s) {
        return s.getClass();
    } 

我得到了同样的错误: required type <String> provided type <? extends String> provided type <? extends String> 我已经看到通过执行以下操作来解决此错误的代码:

        @SuppressWarnings("unchecked")
        Class<T> clazz = (Class<T>) object.getClass();

这是什么意思? 我对这个 generics 问题有什么不明白的地方?

getClass遵循一些有点不寻常的特定规则。 声明的返回类型 Object::getClass 只是Class<?> ,即某种类型的 class 。 但根据文档

实际结果类型是Class<? extends |X|> Class<? extends |X|>其中 |X| 是调用getClass的表达式的 static 类型的擦除。

您的示例中 T 的擦除只是 Object,所以返回是Class<? extends Object> Class<? extends Object> 一切都扩展了 Object,因此与Class<?>相同。

当参数为具体类型String时,擦除也为String,结果为Class<? extends String> Class<? extends String>

Oracle 类型擦除教程

我猜在幕后发生的事情是编译器有效地“覆盖” Object::getClass 并具有更具体的返回类型。 允许子类返回比其父类更具体的类型,但不能不那么具体。 考虑这个有效的代码:

class Foo {
    public Class<? extends List<?>> foo() { return null; } 
}

class Bar extends Foo {
    @Override
    public Class<? extends ArrayList<?>> foo() { return null; }
}

由于这是如何实现的, T obj; obj.getClass(); T obj; obj.getClass(); 将返回Class<?> ,而不是您期望的Class<? extends T> Class<? extends T>

在你的情况下,演员是安全的。

由于类型仍在擦除,因此您只有一个Object object

Class<?> type = object.getClass();

反过来,可以使用:

private <T> T getObject(Object object, Class<T> type) {
   return type.cast(object);
}

上面做了一个动态的运行时转换。 这可能有用:

private final Map<Class<?>, Object> singletonsByType = new HashMap<>();

public <T> void store(Class<T> type, T object) {
    singletonsByType.put(type, object);
}

public <S> S lookup(Class<S> type) {
    return type.cast(singletonsByType.get(type));
}

你可以像这样解决这个问题:

private <T> Class<T> getClass(T object) {
   return (Class<T>)object.getClass();
}

暂无
暂无

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

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