2013-02-04 24 views
3

我有一个类似于递归的泛型方法,但为每个调用调用方法的不同实例。是什么导致与Java泛型和反射这个编译错误?

public <M extends A> void doSomething(Class<M> mClass, M mObject) 
{ 
    // ... Do something with mObject. 

    A object = getObject(); 
    Class<? extends A> objectClass = object.getClass(); 

    doSomething(objectClass, objectClass.cast(object)); // Does not compile. 
} 

private A getObject() {...} 

的问题是有注释的行不能编译,给了以下错误:

The method doSomething(Class, M) in the type MainTest is not applicable for the arguments (Class, capture#3-of ? extends A)

我不太明白为什么编译器不能编译,如果它可以调用doSomething的M =“?扩展A”。

为什么不编译?

+1

泛型请。 Java中没有模板。 – EJP

回答

2

该语言不跟踪这样的通配符(看起来)。你需要做的是捕获通配符,这可以通过类型推断的方法调用完成。

public <M extends A> void doSomething(Class<M> mClass, M mObject) { 
    // ... Do something with mObject. 

    A object = getObject(); 
    Class<? extends A> objectClass = object.getClass(); 
    privateSomething(objectClass, object); 
} 
private <T extends A> void privateSomething(Class<T> objectClass, A object) { 
    doSomething(objectClass, objectClass.cast(object)); // Should compile. 
} 

一如往常,而反射具有一定的用途,它通常是混乱的迹象。

+0

完全同意你的最终评论。 – EJP

4

确定这里是一个原始的解释

你输入你的方法,这样它会接受中号是的

亚型现在您呼叫使用“对象类”,这是一个亚型的方法的但不一定M.的亚型

因此,编译器抱怨......

如果你能解释一下你正在尝试做的多一点,我可以用这样有利于lution。

+0

感谢您的回答。但为什么编译器没有实例化另一个'doSomething'方法呢?这是一种通用的方法。 –

+0

它会在Java 1.5之前工作,但在Java 1.5之后,编译器无法找到匹配的调用方法签名... –

+1

@LeonardoRaele您在制作标题时犯的错误相同。这是泛型,而不是模板。编译器不会在泛型中“实例化”任何东西。你仍然在考虑模板。模板是生成新类型的一种方式:泛型是限制现有类型的一种方式。 – EJP

1

当您要求编译器执行转换时,必须知道执行转换的确切类型。仅仅告诉编译器你并不知道它是A的子类的确切类型摘要。

类告诉编译器该对象的类型是A的子类,但它不告诉编译器用于铸造的确切类型。

你的问题是你试图用泛型替换多态性。正如你正在努力学习,Generic并不是做现代多元化的新现代方式。