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.