情况1: aa保存的是一个BB类型的实例,在编译过程中引用为AA类型,数据存储过程中含有全部BB类的方法和变量;bb只是把aa从AA类型的引用重新定义为BB类型的引用,由于aa中包含BB类的全部方法和变量,所以转型没有问题
情况2: new AA() 中可能不包含BB类的全部变量和方法,强制转换无法实现
思考方法:JAVA中的变量名看成数据指针,new 是在内存中实际的创造一个实例。当创造了一个子类的实例时,指针类型是父类或子类都没有关系。但父类的实例不可能用子类的指针来表达。
强制转型这个叫法来自过去非面向对象的时候吧,对于面向对象来说,只有基本类型 int/float/long/double 之类的数据类型还可以像以前一个叫强制转型,因为它确实是转了型,你想一个 int 在内存里面的二进制布局和 float/double 的 IEEE 浮点格式的二进制布局肯定不同啊。所以需要转型的,这个转型在 int/long 与 float/double 之间转型时会导致永久性的物理性的变化。
而面向对象据说的向下强制转型则不同于基本类型的转型,面向对象的抽象类型的转型本身并不能改变对象的类型,仅仅是把之前由于向上转换而产生的暂时性的隐藏了子类的方法和属性的效果还原成原来的样子。比如 Parent p = new Child() 这将导致 Child 的某些属性和方法在 Parent 中没有而暂时隐藏了,因为你还是可以通过 Java 反射调用的,只是编译器会检测如果你直接调用了 child 的方法(不是通过反射)就会出错,这就是实质上那个 p 还是 Child 类型,只是能不能把它当成 child 来使用。编译器来做这个检查。你明白的是那个对象本身并没有任何变化。
你也可以通过 new String("一个字符串不可能是 Double 的子类") instanceof java.lang.Double 来判断,编译器能立即检测到一个字符串不可能是 Double 的子类而报错。
父类不能转换为子类。你情况二是new的AA,情况一却是new的BB。情况一的AA aa本来就可以写成BB bb的。如果你情况一写成AA aa=new AA(),一样的报错。
因为前一个实际指向一个BB的实例。后者不是。
instanceof 返回 true的才能强制转型。
java中向上转型是默认的,子类继承了父类,自然也就拥有了从父类那里继承过来的方法。但是你向下转型的话,父类可能没有子类拥有的方法,所以会报错。
向上转型描绘的是一些公共的特征,而向下转型是子类自己特殊的定义环境。向上转型就是用父类的引用变量去引用子类的实例,这是允许的。当向上转型后,父类引用变量可以访问属于父类的属性和方法,但是不能访问子类独有的属性和方法。也就是说你向上转型只能去调用父子类中共有且被复写了的方法,如果没有复写,则调用父类的方法。并不是所有的对象都能够向下转型的,只有当这个对象原本是由子类对象通过向上转型得到的时候才能够成功转型,也就不会报错。通俗一点就是在发生向下转型之前一定要发生向上转型。就比如你的情况一,就是先向上转型再向下转型(是不是很无聊 哈哈),这样就不会报错了。需要值得注意一点的是,方法是具有多态性的,但是实例变量是不具备的。
纯手打,给个赞呗~