黑马程序员技术交流社区

标题: 关于多态和向下强制转型 [打印本页]

作者: surce2012    时间: 2013-4-26 15:04
标题: 关于多态和向下强制转型
本帖最后由 surce2012 于 2013-4-26 15:08 编辑

定义一个父类 BaseClass 一个子类SubClass
创建对象 BaseClass bs = new SubClass();
这样就可以实现多态 把子类对象赋给父类对象叫做向上转型这是系统可以自动实现的,但是想要使用bs对象调用子类特有方法时就要强制向下转型
SubClass sc = (SubClass)bs;
我的问题是为什么不把向下转型设计成和向上转型一样可以直接实现而不用强制转换呢?这样就不用强制转换而可以直接调用子类方法,多方便。

作者: 殇_心。    时间: 2013-4-26 15:11
我这样理解:
假设一个父类有2个子类。
向下转的时候。
如果不加的话。是不是会出现混乱?谁知道你这个引用到底是哪个子类?
所以就需要强转动作了。
作者: java冬冬    时间: 2013-4-26 15:37
本帖最后由 java冬冬 于 2013-4-26 15:46 编辑

向下转型往往被认为是不安全的。
SubClass sc = (SubClass)bs;
用bs对象调用子类特有方法的时候要强制向下转型,
只有如此,向下转型才不会出现问题。
在进行向下转型操作时,将特性范围小的对象转换为
特性范围大的对象肯定会出现问题。
但是,如果两个转换的对象特性范围一样大的话,就不会有问题了
另外要说明的是,大家可以放心地使用向上转型,但要慎用向下转型{:soso_e152:}
作者: surce2012    时间: 2013-4-26 15:42
殇_心。 发表于 2013-4-26 15:11
我这样理解:
假设一个父类有2个子类。
向下转的时候。

我也想到这一点了,但是完全可以在命名的时候注意一点, 也有可能sun公司在命名和强制转换上有取舍。
作者: 殇_心。    时间: 2013-4-26 15:52
surce2012 发表于 2013-4-26 15:42
我也想到这一点了,但是完全可以在命名的时候注意一点, 也有可能sun公司在命名和强制转换上有取舍。 ...

注意。
你要记住写代码不是一个人在奋斗啊。
你写的爽了。。  你队友就悲催咯。
作者: HM汪磊    时间: 2013-4-26 19:28
SubClass sc = (SubClass)bs;这句中sc只能调用子类覆盖了父类中方法的方法,而不能调用子类自己特有的方法
如果要调用子类特有的方法必须进行向下转型!!!
作者: 夏凡    时间: 2013-5-2 22:36
楼主有这种想法是很值得提倡的,但是这个不是我们初学者应该过分去追究的,毕竟这是设计java语言的工程师的杰作,这样的设计总有他们的理由的,对于现阶段的我们来说这些就是一些需要遵守的规则
作者: 不喝茶的陆羽    时间: 2013-5-2 23:56
本帖最后由 不喝茶的陆羽 于 2013-5-3 00:09 编辑

子类转型成父类是向上转型,反过来说,父类转型成子类就是向下转型。但是,向下转型可能会带来一些问题:我们可以说麻雀是鸟,但不能说鸟就是麻雀。来看下面的例子:

A类:

package a.b;

public class A {

void aMthod() {

       System.out.println("A method");

}

}

A的子类B:

package a.b;

public class B extends A {

void bMethod1() {

       System.out.println("B method 1");

}

void bMethod2() {

       System.out.println("B method 2");

}

}

C类:

package a.b;

public class C {

     public static void main(String[] args) {

            A a1 = new B(); // 向上转型

            a1.aMthod();    // 调用父类aMthod(),a1遗失B类方法bMethod1()、bMethod2()

            B b1 = (B) a1; // 向下转型,编译无错误,运行时无错误

            b1.aMthod();    // 调用父类A方法

            b1.bMethod1(); // 调用B类方法

            b1.bMethod2(); // 调用B类方法

            A a2 = new A();

            B b2 = (B) a2; // 向下转型,编译无错误,运行时将出错

            b2.aMthod();

            b2.bMethod1();

            b2.bMethod2();

     }

}

从上面的代码我们可以得出这样一个结论:向下转型需要使用强制转换。运行C程序,控制台将输出:

Exception in thread "main" java.lang.ClassCastException:  a.b.A cannot be cast to a.b.B at
                a.b.C.main(C.java:14)

A method

A method

B method 1

B method 2

其实向下转型代码后的注释已经提示你将发生运行时错误。为什么前一句向下转型代码可以,而后一句代码却出错?这是因为a1指向一个子类B的对象,所以子类B的实例对象b1当然也可以指向a1。而a2是一个父类对象,子类对象b2不能指向父类对象a2。那么如何避免在执行向下转型时发生运行时ClassCastException异常?使用的instanceof就可以了。我们修改一下C类的代码:

A a2 = new A();

if (a2 instanceof B) {

B b2 = (B) a2;

b2.aMthod();

b2.bMethod1();

b2.bMethod2();

}

这样处理后,就不用担心类型转换时发生ClassCastException异常了。
作者: 不喝茶的陆羽    时间: 2013-5-2 23:59
这个老师在视频中应该是有讲过的..不赞同楼上说的不应该深究,要想做一名好的程序员本来就应该知道缘由的.
作者: 王廷顺    时间: 2013-5-3 11:44
java语言是用来解决现实生活中的问题 ,设计时肯定要遵循描述现实世界的原理,打个比方:狗一定是动物,但动物不一定就是狗,还可能有很多,可能是猫、猪、鸡,鸭,大鹅等等,这也许是用多态描述现实世界的原因吧,向上和向下转型自然也就顺理成章的出现了,并且对应的向下转型也就存在可能的弊端,因为要对应对现实世界的描述嘛。
作者: xiewen    时间: 2013-5-4 00:43
王廷顺 发表于 2013-5-3 11:44
java语言是用来解决现实生活中的问题 ,设计时肯定要遵循描述现实世界的原理,打个比方:狗一定是动物,但 ...

你这个比喻很好!
作者: 汪平乐    时间: 2013-5-6 12:37
不喝茶的陆羽 发表于 2013-5-2 23:56
子类转型成父类是向上转型,反过来说,父类转型成子类就是向下转型。但是,向下转型可能会带来一些问题:我 ...

不用担心类型转换时发生ClassCastException异常这里if (a2 instanceof B)只是解决了不发生异常,但不可以正常输出,所以你调用B类的方法没意义?
作者: Leo_yeung    时间: 2013-10-10 18:20
父类类型如果可以自动转换为子类类型,这就不符合逻辑了;
同时也是不安全的,因为是子类继承父类,子类可以调用父类的功能,父类怎么能使用子类特有的功能呢?
如同基本数据类型中的向下转型一样,需要强制转换。如果自动转换可的,则会损失精度。
因为子类不确定,可能会导致ClassCastException异常;所以,通常在转换前要使用instanceof判断要转换的类型是不是子类的实例。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2