2013-12-20 57 views
1

两类:上溯造型给人ClassCastException异常

public class ClassA implements ClassC { 
    private static final long serialVersionUID = 1111111111111111111L; 
    public String varA; 
} 

public class ClassB extends ClassA implements ClassC { 
    private static final long serialVersionUID = 4604935970051141456L; 
    public String varB; 
} 

在我的代码,我有这样的声明: ClassB classB;

和方法

myMethod的()

返回一个ClassA目的。

如果我写:

classB = (ClassB) myMethod(); 

我认为我将有:

classB.varA = <a value from myMethod()> 
classB.varB = null 

,但事实并非如此:我收到ClassCastException异常

为什么?那么如何快速分配myMethod()ClassB

+0

显示所有相关代码。我不确定我了解你想要做什么。 –

+0

一个强制转换不会改变一个对象的类,它只是验证该对象是那个类(或该类的某个子类)。如果你的myMethod返回了一个ClassB对象,但是把它输入为ClassA,那么这个转换就可以工作。 –

+0

我不明白为什么B类实现C类,如果A类实现C类,B类扩展A类,那么B类也不隐式实现C类接口? – Lucas

回答

1

的问题是,你想垂头丧气一个ClassAClassB,这是不允许的,因为实际的对象可能是ClassX(的ClassA另一个子类)不具有明确的转换。

请看下面的例子,这将抛出ClassCastException(但编译就好):

public class Main { 
    public static void main(String[] args) { 
     SubB var = (SubB) someMethod();   
    } 

    private static Super someMethod(){ 
     return new SubA(); 
    } 
} 

class Super { } 
class SubA extends Super { } 
class SubB extends Super { } 

代码编译完美:

  • someMethod()返回类Super类型。
  • SubA延伸Super所以这种方法定义不违反
  • SubB扩展Super所以它可以投Super类型的对象,以SubB

然而,当你执行这个,你试着投了SubA类型的对象到SubB,这是不可能的。

图片的标题说明:

  • 不要使用ClassC在此名称与类名的interface
  • 认沽层次的小例子(超级< - >子),而不是(A < - >乙< - > C)
0

ClassA不是ClassB可互换的。将您的方法更改为返回ClassC(界面),并将该参考存储为ClassC,然后您可以使用ClassAClassB。 A是一个C和B是一个C,但是A不是一个B,尽管B是一个A.如果这有帮助。

+0

请注意,您可以将ClassB对象存储在类型为ClassA的引用中,并将其视为ClassA。如果您想将其视为ClassB,则可以使用(ClassB)获取类型为ClassB的引用。 –

+0

'B'扩展'A',所以'ClassB'就是'ClassA'。我已经把我认为是问题的答案放在了答案中。 –

1

在Java中强制转换不像dynamic_cast < ...> C++中的指针。对于后者,如果类型不兼容,则结果为空指针。在Java中,投射不兼容的引用导致ClassCastException

通常的Java习惯用法是使用instanceof事先测试参考,然后只在结果为真时执行强制转换。例如,

ClassA a = myMethod(); 
if (a instanceof ClassB) { 
    ClassB b = (ClassB) a; 
    ... 
}