是什么让对象分配与另一个类兼容?

时间:2014-09-16 04:25:38

标签: java inheritance casting

我想知道具体允许将一个类的对象作为另一个类进行转换。查看Class.isInstance(Object obj)javadoc,它表明对象必须与...分配兼容'与另一个类,以便投射到该类。但是什么构成'赋值兼容'?

我试图找出以下内容如何返回ClassCastException:

public class A
{
    multiple private attributes
    No constructor
    multiple public methods
}

public class B extends A
{
    blank default constructor
    2 additional private attributes
    4 additional public getter / setter methods for these attributes
}

该行

B b = (B)variable.getA()  // where getA() returned an instance of class A

返回ClassCastException A不能转换为B.我知道从父类转换为子类是个坏主意。我没有编写有问题的代码,我只是在生产支持能力中查看它。

B类是代码库中唯一一个从A扩展的类。因此getA()的结果不是A的另一个子类(比如C)的对象,它被转换为A.

那么为什么在这种情况下Java不会将类A的对象强制转换为看似兼容的类B?

5 个答案:

答案 0 :(得分:2)

考虑以下两种情况:

A a = new B();
B b = (B)a;    <--  Ok.

A a = new A();
B b = (B)a;    <--  ClassCastException

因此,为了将对象强制转换为B,它必须是B的实例(或B的子类)。

在你的情况下,它是A的实例。

答案 1 :(得分:1)

Class.isInstance(Object obj)的javadoc给出了assignment compatible

的定义
  

具体来说,如果此Class对象表示声明的类,则如果指定的Object参数是所表示的类(或其任何子类)的实例,则此方法返回true ;否则返回false。如果此Class对象表示数组类,则如果可以通过标识转换或扩展引用转换将指定的Object参数转换为数组类的对象,则此方法返回true;否则返回false。 如果此Class对象表示接口,则如果指定Object参数的类或任何超类实现此接口,则此方法返回true ;否则返回false。如果此Class对象表示基本类型,则此方法返回false。

基本上,如果类型A扩展或实现类型B,则可以将类型A的对象分配给类型B的变量。

答案 2 :(得分:0)

抛出以指示代码已尝试将对象强制转换为不是实例的子类。例如,以下代码生成ClassCastException

 Object x = new Integer(0);
 System.out.println((String)x);

更多信息herehere

答案 3 :(得分:0)

如果我们用有意义的名字替换A和B来帮助我们思考问题,那么答案就会变得更加清晰。如果A成为哺乳动物而B是狗,那么我们可以合理地说所有狗都是哺乳动物,但我们不能说所有的哺乳动物都是狗。即使他们表面上共享相同的属性,也不能保证所有哺乳动物都能履行作为狗的合同,编译器不应该尝试这样做。

答案 4 :(得分:0)

只想添加官方规范以支持 Ricardo's correct answer“如果类型A扩展或实现类型B,则可以将类型A的对象分配给类型B的变量”:

JLS定义分配兼容性如下:

5.2. Assignment Contexts

  

如果可以通过赋值转换将表达式的类型转换为变量的类型,那么我们说表达式(或其值)可以分配给变量,或者等效地,表达式的类型可以与赋值兼容变量的类型。

“评估转换” 一词仅被定义为应用“任务上下文”一章中给出的列表中的适当转换:

  

术语“转换”还用于描述特定上下文中允许的任何转换,而没有具体说明。例如,我们说作为局部变量的初始化程序的表达式要进行“赋值转换”,这意味着将根据赋值上下文的规则为该表达式隐式选择特定的转换。

与引用类型最相关的是

5.1.5. Widening Reference Conversion

  

存在从任何引用类型S到任何引用类型T的扩展引用转换,条件是S是T的子类型(第4.10节)。

子类型包括已实现的接口(请参见4.10.2. Subtyping among Class and Interface Types )。

对于数字和泛型类型,还有其他规则,但它们与问题中给出的示例无关。