无法弄清楚这个泛型问题。我有这些接口:
public interface LoadableObject
{
}
public interface LoadableObjectFactory<T>
{
}
现在我想这样做:
public class ObjectReference<T extends LoadableObject>
{
Class<? extends LoadableObjectFactory<T>> _cls;
public ObjectReference(LoadableObjectFactory<T> obj)
{
_cls = obj.getClass();
}
}
但是我收到了一个错误:
incompatible types
found : java.lang.Class<capture#885 of ? extends test.LoadableObjectFactory>
required: java.lang.Class<? extends test.LoadableObjectFactory<T>>
_cls = obj.getClass();
^
如果我在LoadableObjectFactory
的定义中移除了_cls
的类型参数,我可以编译,但是它是一个不完整的类型...是否有我遗漏的东西或者它只是不可能?
答案 0 :(得分:4)
运行时的getClass()提供了Class&lt;?&gt;。由于类型擦除,关于通用参数的信息不可用。你必须做一个演员
@SuppressWarnings("unchecked")
public ObjectReference(LoadableObjectFactory<T> obj)
{
_cls = (Class<? extends LoadableObjectFactory<T>>) obj.getClass();
}
让它运作
答案 1 :(得分:4)
这是info about type erasure,直接来自马的嘴,可以这么说。
这个东西伤到了我的思考,所以我不会试图解释它。可以说有一些操作你期望工作,但是因为Java“忘记”模块之间类型的通用细节,所以它们没有。
你可能无法使用这些信息,但是在Java中构建泛型的人已经去了并设计了一种全新的类似Java的语言:它被称为Scala。 Scala可以更好地处理类型和泛型;你可以说它在这方面做的一切都是正确的。它也可以在JVM中运行,您可以在Scala和Java类之间调用。
我个人对Scala的看法是,它是一个巧妙管理复杂类型的系统,偶然也可以用作编程语言。 :)
答案 2 :(得分:1)
我不会指责'类型擦除'。静态查看代码,它显然是安全的,它应该在更好的世界中传递编译器。
Java Generics太复杂了,不值得花时间弄清楚每一个细节。如果你知道你比编译器更清楚,那就做任何事情来绕过它。
答案 3 :(得分:0)
我原以为LoadableObjectFactory看起来像这样:
public interface LoadableObjectFactory<T extends LoadableObject>
说过--Object.getClass()返回一个无类型的类,所以你必须强制转换它。要修复它,必须将java.lang.Object的签名更改为
class Object<T extends Object<T>> {
native Class<T> getClass();
}
但是对java.lang.Object的改动将涉及到几乎无处不在的大手术。