2017-07-03 61 views
0

我以为你不能将Parent转换为Child,并且只能将Child转换为Parent。或者至少如果你这样做,你将不被允许访问孩子的功能。将父母给予孩子 - 数组中的奇怪行为

然后我看到,Java将允许我明确投父到子:

a=(B)a; 

,但不会允许

bArray[0]=a 

a.testB(); 

然而,这是确定的:

bArray[1]=(B)a; 

所以是这样的:

bArray[1].testB(); 

可有人请解释一下是怎么回事!?如何给父类授予一个子类的功能?为什么第一次尝试将数组放入阵列不起作用,但第二次尝试呢?它不应该一样吗?

class A { 
    public void testA() { 
    } 
} 

class B extends A { 
    public void testB() { 
    } 
} 

public class polymorphicObjects { 
    public static void main(String[] args) { 
     B bArray[] = new B[5];  
     A a = new A(); 
     A ab = new B(); 

     a = (B)a; //didnt think you could do this 
     bArray[0] = a; //but if I can the why doesnt this work? 
     a.testB(); //or this 
     bArray[1] =(B)a; //but this does work 
     bArray[1].testB(); //and so does this!? 
    } 
} 
+3

** //为什么不工作?** - 因为您声明'a'是A型的,所以不要紧。 'A a =(B)new A();'。变量'a'仍然是'A'类型,因为那是你如何定义它的。无论如何。我确定其实这些都不起作用,如果你尝试运行它,你只会得到一个ClassCastException。仅仅因为它编译不会意味着它有效。 –

+0

哈是类演员异常。我正在为OCJA学习,他们一直在向我抛出奇怪的东西。没想到打编译。谢谢你,先生。 – Mason

回答

0

是否运行bArray[1].testB();实际工作?至少应该抛出一个ClassCastException。在testB()方法内部添加一个打印语句应该有帮助。

所以在这里,你说a = (B)a;这是非常明确地铸造一个类型B,但它实际上并没有任何意义。

考虑到这一点,在第一行bArray[0] = a;中不起作用,因为它不再被明确强制转换,所以编译器会抱怨说您提供的类型不匹配。

在随后的行bArray[1] = (B)a;中,您明确地告诉编译器A是B类型的,因此它不会对您发出警告......尽管对方法testB()的调用在运行时会失败。

+0

你是正确的演员例外。我没想过要编译它。我一直在为OCJA学习,现在只是依靠Eclipse来告诉我红线。猜猜在编译之前它无法捕捉到所有的东西。谢谢! – Mason

+0

如果你不介意的话,如果你接受我的回答,我会很感激的:)我只是刚刚开始回报我在大学生涯中依赖的社区。 – SaxyPandaBear

+0

我做过了,但是我没有足够的Java Stackoverflow声望来进行计数:/。我主要只是一个潜伏者哈哈。当我有足够的代表时,我会再次投票! – Mason

0

在Java中,铸造具有非常具体的含义(与C语言不同,例如)。你必须区分你的对象实际拥有什么类,以及编译器对某些表达式的类是怎么想的。

铸造不会改变实际的对象类,但只会改变编译器对表达式类的看法。

让我们通过代码:

new A()总会给你一个类的对象,编译器知道。

您存储到参考变量a,声明为类A的,所以从声明(不是new A()表达)编译器知道变量a具有A类(允许亚类)。

随着投式(B) a你不改变任何东西 - 这就是存储在a对象,只是断言的编译器,您作为开发商,知道存储在a的对象是B型的(这是不真的,在你的情况下,这是一个A,而不是B)。编译器不够聪明,所以他把表达式(B) a视为有效的并且是B类。他允许你从A转换到B,因为B是A的子类,所以A类的变量可能非常好包含B类的对象(例如A a = new B();将完全可以)。在运行时,JVM将检查实际的对象类并提出ClassCastException,因为它发现它不是来自子类B的A。

With a = (B) a;将同一个对象存储回它来自的同一个变量。

你问bArray[0] = a;这不,因为编译器编译,a包含A类的一个对象,数组需要B. bArray[1] = (B) a;将编译,但抛出ClassCastException只要变量仍然包含运行时与A类相同的对象。

bArray[1].testB();编译因为编译器知道在bArray所有元素都是B类,而B类有这个方法。由于试图将不属于B类的对象存储到bArray中(在编译时bArray[0] = a;或运行时bArray[1] = (B) a;)将不起作用,因此调用testB()方法是安全的。

+0

这是一个很好的解释。谢谢。当我有足够的声誉来处理问题时,我会回来为这个答案投票。 – Mason