Java:层次结构继承的强制转换规则

Java:层次结构继承的强制转换规则,java,casting,Java,Casting,如图所示,我有一个继承类的层次结构。我正在寻找一个通用规则,如从上到下或从下到上规则 我的意思是,我可以投哪一个?为什么呢? Child ch; Parent p=(Parent ) ch; 或 编辑 因为我有时像个盲人,我没有看到你没有初始化你的变量。 因此,以下是关于此初始化的解释: 案例1 案例2 结束编辑 您可以将子项转换为父项,因为子项由于继承而也是父项 您不能将父项强制转换为子项,因为父项是实例化为父项,而不是子项 我举个例子: 我有一支钢笔。这也是一个用来写作的工具 但是如果我拿

如图所示,我有一个继承类的层次结构。我正在寻找一个通用规则,如
从上到下
从下到上
规则

我的意思是,我可以投哪一个?为什么呢?

Child ch;
Parent p=(Parent ) ch;

编辑

因为我有时像个盲人,我没有看到你没有初始化你的变量。 因此,以下是关于此初始化的解释:

案例1

案例2

结束编辑

您可以将
子项
转换为
父项
,因为
子项
由于继承而也是
父项

您不能将
父项
强制转换为
子项
,因为
父项
是实例化为
父项
,而不是
子项

我举个例子:

我有一支钢笔。这也是一个用来写作的工具

但是如果我拿一个标准工具(比如说它有一个句柄和一个函数),我就不能把它看成是一支钢笔,因为它不能写。 让我们更进一步

现在,我有了一支双色笔!!!太棒了,我喜欢

这是一支钢笔,它是一种工具,所以我可以把它看作是Bicolor Pen,作为笔和工具! 如果我拿一支普通的钢笔,它没有双色!它只是一支钢笔,也是一种工具

和代码示例

public class Human {
    protected String chromosome;

    private int legs, arms = 2;
    private int head = 1;

}

public class Man extends Human {

     private boolean drinkBeer = true;       

     public Man() {
        chromosome = "XY";
     }
}

public class Woman extends Human {
    private boolean loveHandbags = true;

    public Woman() {
        chromosome = "XX";
    }

}
男人也是人,因为他有两条腿,两条胳膊和一个头。我也是一个女人。 但是,如果我有一个人类,我不知道他的特殊种类,我就不能说它的决定染色体是什么(或者他是否喜欢啤酒或手提包)

我希望我的解释能帮助你理解,我向女士们道歉:)

编辑


我不是说它是否编译(它将编译)。但是在运行时您将有一个
ClassCastException

您可以始终隐式地将
Child
类型的引用转换为
Parent
类型的引用。您可以显式地将类型为
Parent
的引用强制转换为类型为
Child
的引用,但如果引用的对象实际上不是
子对象,则在运行时使用
ClassCastException
可能会失败

不过,这可能有助于说明为什么会出现这种情况

具有类型为
Parent
的引用真正意味着什么?这基本上意味着您可以使用
Parent
定义的任何方法(我在这里做了一些修饰,特别是关于字段和
null
s)。如果子级扩展父级,则它继承所有这些方法。因此,将
子对象
类型的对象视为
父对象
类型的对象总是安全的,因为您希望从该
父对象
引用中使用的任何方法也必须存在于
子对象
对象上

Child c = getSomeObject();
Parent p = c;
p.doSomethingParental();
即使引用
p
指向一个
Child
对象,该
Child
继承了
doSomethingParental
方法,因此该代码工作正常

反过来怎么样?好吧,假设
Child扩展了Parent
并添加了一个方法
beAGoodChild()
。现在您有了一个
父级
引用,并且希望将其强制转换为
子级

Parent p = getSomeOtherObject();
Child c = (Child) p;
c.beAGoodChild();
显然,最后一行只能在
c
确实是
子级
(而不仅仅是普通的ol'
父级
)的情况下使用。如果不是,那么在第二行,我们在那里进行铸造,是发现错误的合理位置。这样更容易更快地发现虫子;与其在我们尝试使用他们没有的方法时发现它们(这可能发生在角色转换后很久),不如在角色转换时捕获它们,然后保证对
c.beAGoodChild()
的任何调用都会成功。基本上,它允许您忽略“这真的是一个孩子吗?”的问题,除非在某些特定的情况下(即,在施法时)。

允许您对任一施法进行编码。第一种情况甚至不需要强制转换就可以被编译器接受

但是,在执行时,第二种情况下的变量
p
必须实际引用
Child
的实例(或
Child
的某个子类),否则将引发强制转换检查异常


请记住,强制转换实际上并没有更改对象的类型,它只是断言/验证是否允许将该对象视为指定的类型。

是的,可以将子对象强制转换为父对象,因此以下操作将起作用

Child ch = new Child();
Parent p=(Parent) ch;  
System.out.println("Working!!");
虽然这不起作用:

Parent p= new Parent();
Child ch = (Parent)p;  
System.out.println("won't work!!");
//获取不兼容类型错误


请注意,在您的代码中,您没有初始化任何从未使用过新运算符的对象,因此您将得到“p/ch never initialized error”。

有两种类型的向上和向下转换,但Java只允许“向上转换”,您也可以在Java中“向下转换”,但它可以引发运行时异常。在您的情况下,它也会抛出一个运行时异常

“向上投射”:这意味着当你们有子类时,你们可以将它投射到父类,所以这是合法的投射

“向下转换”意味着您希望将父类转换为子类。在爪哇是危险的。若对象可以转换为目标类型,那个么它可以工作,否则它会抛出运行时异常

在向下广播的情况下,程序可以抛出运行时异常(java.lang.ClassCastException)

为什么将父母交给孩子是危险的:-

当我们使用(强制转换)OBJ1时,它会尝试将该OBJ1强制转换为目标类型。比如说

Child c = (Child)p1. 
它将尝试将p1强制转换为子类型。p1可以具有子类引用或父类引用

p1 = new Parent() // It would not work and throw an exception (java.lang.ClassCastException) see explanation below

下面是一个简单的原因,将对象强制转换为某个特定的类型允许我们将其视为该类型的对象。所以,如果我们将子对象强制转换为父对象,那么我们可以将其视为父对象,并可以调用任何父方法。霍维夫
Parent p= new Parent();
Child ch = (Parent)p;  
System.out.println("won't work!!");
Child c = (Child)p1. 
p1 = new Parent() // It would not work and throw an exception (java.lang.ClassCastException) see explanation below
p1 = new Child()   // It will work.