标题听起来有点复杂,但事实上问题很简单。 我有以下方法:
AbstractClassA<AbstractClassB> myMethod() {...}
我想这样调用它:
ClassAImpl<ClassBImpl> result = myMethod();
问题在于无论我尝试什么,我最终都会遇到unchecked cast警告或编译错误。
这样做的正确方法是什么?
答案 0 :(得分:1)
一切都取决于。最简单的答案是,您只需要将myMethod
的结果转换为与结果相同的类型。假设我们从问题中解决了所有泛型问题,例如:
public class Demo {
private abstract class AbstractClassA {}
private class ClassAImpl extends AbstractClassA {}
private abstract class AbstractClassB {}
private class ClassBImpl extends AbstractClassB {}
Demo() {
ClassAImpl result = myMethod();
}
public AbstractClassA myMethod() {
return new ClassAImpl();
}
public static void main(String[] args) {
new Demo();
}
}
对myMethod
的调用仍然是编译器错误,因为类型不匹配。考虑这一点的一个好方法是想象你对myMethod
正文中的代码一无所知。你怎么知道它返回ClassAImpl
而不是AbstractClassA
的其他子类型?因此,为了使其工作,您需要像这样调用myMethod
:
ClassAImpl result = (ClassAImpl)myMethod()
至于泛型位,您可能希望您的方法签名类似于:
public AbstractClassA<? extends AbstractClassB> myMethod()
但也许想要这样的事情:
public AbstractClassA<ClassBImpl> myMethod()
甚至:
public ClassAImpl<ClassBImpl> myMethod()
除了最后一个之外的所有内容都需要一些明确的演员。
答案 1 :(得分:1)
为什么你到底会这样做呢?你的设计是错误的,或者你遗漏了一些重要的信息。如果myMethod
与尝试的调用位于同一个类中,那么您的调用者可以了解有关如何实现该方法的信息,那么您应该创建一个返回更具体类型的私有myMethodAux
。但是,您可能仍会遇到方差问题,因为ClassAImpl<ClassBImpl>
不是AbstractClassA<AbstractClassB>
的子类。它是AbstractClassA<? extends AbstractClassB>
的子类。
上面的评论似乎表明您不了解Java中子类型关系的这种差异限制。
答案 2 :(得分:0)
如果没有显式类型转换,则无法将超类型指定为子类型。
在向下投射之前使用instanceof
运算符。
尝试Class#isInstance()
abstract class AbstractClassA<T extends AbstractClassB> {}
abstract class AbstractClassB {}
class ClassAImpl<T extends AbstractClassB> extends AbstractClassA<T> {}
class ClassBImpl extends AbstractClassB {}
...
public static AbstractClassA<? extends AbstractClassB> myMethod() {
return new ClassAImpl<ClassBImpl>();
}
...
AbstractClassA<? extends AbstractClassB> returnValue=myMethod();
if(returnValue.getClass().isInstance(new ClassAImpl<ClassBImpl>())){
ClassAImpl<ClassBImpl> result=(ClassAImpl<ClassBImpl>)returnValue;
...
}