如图所示,我有一个继承类的层次结构。我正在寻找一般规则up to down
或down to up
规则。
我的意思是,允许我投哪一个?为什么?
Child ch;
Parent p=(Parent ) ch;
OR
Parent p;
Child ch=(Child ) p;
答案 0 :(得分:1)
您始终可以隐式地将类型为Child
的引用强制转换为Parent
类型的引用。您可以显式地将Parent
类型的引用强制转换为类型为Child
的引用,但如果引用的对象实际上不是{{1},则在运行时可能会失败ClassCastException
}}
虽然这可能有助于说明为什么。
拥有Child
类型的引用意味着什么?它基本上意味着你可以使用Parent
定义的任何方法(我在这里做了一些修饰,特别是关于字段和Parent
s)。如果null
,则它继承所有这些方法。因此,将Child extends Parent
类型的对象视为Child
类型的对象始终是安全的,因为您希望从Parent
中使用任何方法Parent
1}}引用也必须存在于Child
对象上。
Child c = getSomeObject();
Parent p = c;
p.doSomethingParental();
尽管引用p
指向Child
对象,但Child
继承了doSomethingParental
方法,因此此代码可以正常工作。
反过来怎么样?好吧,让我们说Child extends Parent
并添加方法beAGoodChild()
。现在您有一个Parent
引用,并且您希望将其转换为Child
:
Parent p = getSomeOtherObject();
Child c = (Child) p;
c.beAGoodChild();
显然,最后一行只有在c
真的是Child
时才有效(而不仅仅是一个普通的' Parent
)。如果不是,那么抓住这个错误的合理位置就在第二行,我们在那里进行投射。这样可以更快地发现错误;当我们尝试使用他们没有的方法(这可能在铸造发生很久之后发生)时,而不是发现它们,如果我们在施法时间抓住它们会更好,然后保证对c.beAGoodChild()
的任何调用都将成功。基本上,它可以让你忽略"这真的是一个孩子的问题?"除非在某些特定情况下(即铸造时)。
答案 1 :(得分:1)
您可以代码进行投射。第一种情况甚至不需要进行转换以便编译器接受。
但是,在执行时,第二种情况中的变量p
必须实际引用Child
的实例(或Child
的某个子类),否则将引发转换检查异常
请记住,强制转换实际上并不会更改对象的类型,它只是断言/验证允许将对象视为指定的类型。
答案 2 :(得分:-1)
修改强>
由于我有时像个瞎子,我没有看到你没有初始化你的变量。 所以,这是一个考虑这种初始化的解释:
案例1
Child ch = new Child();
Parent p=(Parent ) ch;
案例2
Parent p = new Parent();
Child ch=(Child ) p;
结束编辑
您可以将Child
转换为Parent
,因为Child
也是Parent
,这要归功于继承。
您无法将Parent
转换为Child
,因为Parent
是Parent
的实例,因此不是Child
。
我举了一个例子:
我有一支笔。这也是一个用来写作的工具。
但是,如果我采用标准工具(让我们说它有一个手柄和一个功能),我不能把它当作一支笔,因为它不会写。
让我们走得更远
现在,我有一支双色笔!!!太好了,我很喜欢!
它是一支笔,它是一个工具,所以我可以把它当作双色笔,作为笔和工具!
如果我拿普通的笔,它没有双色!它只是一支钢笔,也是一种工具。
以及代码示例
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
:https://ideone.com/kolTwa
答案 3 :(得分:-1)
是的,可以将Child强制转换为Parent,以便后续工作
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从未初始化错误'。
答案 4 :(得分:-2)
有两种类型的向上和向下,但Java仅允许" UPCASTING"你也可以" DOWNCAST"在JAVA但它可以抛出运行时异常。它也会在你的情况下抛出一个运行时异常。
" UPCASTING":这意味着当你有子课时,你可以将它转换为父类,所以这是合法的演员。
"向下转换"这意味着您想要将Parent类转换为Child类。这是Java中的危险。如果object可以转换为目标类型,那么它可以正常工作,否则会引发运行时异常。
如果是DOWNCASTING程序可以抛出运行时异常(java.lang.ClassCastException)。
为什么将父母送入儿童是危险的: -
当我们使用(强制转换)OBJ1时,它会尝试将obj1强制转换为目标类型。例如
Child c = (Child)p1.
它会尝试将p1转换为Child类型。 p1可以有子类引用或父类引用..
p1 = new Parent() // It would not work and throw an exception (java.lang.ClassCastException) see explanation below
OR
p1 = new Child() // It will work.
这是一个简单的原因将对象转换为某种特定类型允许我们将其视为该类型的对象。因此,如果我们将child转换为parent,那么我们可以将它视为父对象,并且可以调用任何父方法。然而,方法的调用转到实际类型,在这种情况下,当我们已经将对象转换为Parent时,将执行子类的函数。
子类将具有在Parent类中定义的所有可用方法和实例变量。因此,如果将子对象转换为父类并调用父类的任何方法,它将完美地工作(但它将调用子类方法)。
在其他情况下,在子类中定义了一些额外的方法/实例变量。因此,当您将父对象强制转换为子类并尝试调用此类方法(在子类中定义的额外方法)时,它将无法在父对象中找到并产生问题。