黑马程序员技术交流社区

标题: JAVA中关于继承,上转型下转型的问题 [打印本页]

作者: 刘宏庆    时间: 2011-7-25 13:39
标题: JAVA中关于继承,上转型下转型的问题
一个对象只能有一种确切的数据类型
一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法。
public class Test4 {
public int score;
public String name;
}
class Test41 extends Test4{
public int age;
public int classnum;

main里边是        
Test4 t41=new Test41();
t41.age=10;
果然出错。我知道这样子不能调出age。但我知其然不知期所以然,麻烦各位前辈给点指点,谢谢。还想请问一下,上转型下转型,是什么意思?
作者: 詹季春    时间: 2011-7-25 13:42
:) 张老师语录
Java编译阶段是按照严格的语法来进行程序检测的,就是按声明变量所用的类型来检测 (等号左边),
那么[code=java]Test4 t41=new Test41();
t41.age=10; [/code]编译类型为父类,所以在编译的时候就会在这个类里面检测有没有这个属性,没有就报错

注:Java引用变量有两个类型,一个是编译时候的类型,一个是运行时候的类型,
编译时候的类型由声明该变量的时候使用的类型决定,
运行时候的类型由时机赋值给该变量的对象绝对
----------------------------关于多态------------
如果编译类型和运行类型不一样,也就是出现所谓的多态
就像楼上主函数创建对象时候的一样但是要有三个必要的条件
1、要有继承
2、要有重写
3、父类引用指向子类的对象
------------------------------------------------
因为子类是一种特殊的父类,所以Java允许把一个子类对象直接赋值给一个父类引用变量,无需任何类型转换,这就是向上转型,一般是由由系统自动完成的
总结:
方法:引用类型的变量在编译阶段只能调用编译时候类型所具有的方法,但是运行的时候就执行他运行时候类型所具有的方法,所以在编写代码的时候,引用变量只能调用声明这个变量时候所用类里面包含的方法


属性:属性没有多态之说,如果上面父类之中也有age属性的话,并且有初始值,那么在运行的时候输出的是父类的实例属性,所以引用变量来访问其包含的实例属性的时候,系统总是试图把访问他编译时候类所定义的属性,并不是他运行时候锁定义的属性

最后用一个程序来阐明前面的观点[code=java]class BaseClass
{
        public int book = 6;
        public void base()
        {
                System.out.println("父类的普通方法");
        }
        public void test()
        {
                System.out.println("父类的被覆盖的方法");
        }
}
public class SubClass extends BaseClass
{
        //重新定义一个book实例属性覆盖父类的book实例属性
        public String book = "定义一个book实例属性覆盖父类的book实例属性";
        public void test()
        {
                System.out.println("子类的覆盖父类的方法");
        }
        public void sub()
        {
                System.out.println("子类的普通方法");
        }
        public static void main(String[] args)
        {
                //下面编译时类型和运行时类型完全一样,因此不存在多态
                BaseClass bc = new BaseClass();
                //输出 6
                System.out.println(bc.book);
                //下面两次调用将执行BaseClass的方法
                bc.base();
                bc.test();

                //下面编译时类型和运行时类型完全一样,因此不存在多态
                SubClass sc = new SubClass();
                //输出"轻量级J2EE企业应用实战"
                System.out.println(sc.book);
                //下面调用将执行从父类继承到的base方法
                sc.base();
                //下面调用将执行从当前类的test方法
                sc.test();
                //下面调用将执行从当前类的sub方法
                sc.sub();

                //下面编译时类型和运行时类型不一样,多态发生
                BaseClass ploymophicBc = new SubClass();
                //输出 6 —— 表明访问的是父类属性
                System.out.println(ploymophicBc.book);
                //下面调用将执行从父类继承到的base方法
                ploymophicBc.base();
                //下面调用将执行从当前类的test方法
                ploymophicBc.test();
                //因为ploymophicBc的编译类型是BaseClass,BaseClass类没有提供sub方法
                //所以下面代码编译时会出现错误。
                //ploymophicBc.sub();
        }
}[/code]
[ 本帖最后由 詹季春 于 2011-07-25  14:06 编辑 ]
作者: 匿名    时间: 2011-7-25 15:16
标题: 回复 楼主 的帖子
子类是父类的一个特例,父类有的属性子类肯定有,子类有的父类不一定有。
作者: 匿名    时间: 2011-7-25 19:30
一个子类对象的类型可以向上转换成它的父类类型,既是一个子类对象可以当作父类对象使用,这种转换是安全的,java编译器会自动进行。
一个父类对象一般是不能向下转换成它的子类类型,既是一个父类对象一般不可以当作子类对象使用,这是因为子类中包含的信息父类中不一定有。一个父类对象转换成它的子类类型时,必须确保其引用的是该子类的一个对象,否则会发生错误,为了防止这种情况发生,可以引用运算符instanceof。而你就没引用实例对象当然发生错误了。
作者: 王松朝    时间: 2011-7-25 20:10
最初的"继承图"(忘记叫什么了,也忘记谁在什么时候首次提出的,一会去查查)父类总是在子类的上面,所以叫向上\下转型.
子类继承自父类,并可以扩展,所以子类总是大于等于父类的功能,当把一个子类对象传给父类时,类似于强制类型转换(但又不太相同,尤其是向下转型),精度会变小,所以向上转型是安全的,不会出现未知对象.
向下转型却不是安全的,但有特殊的机制保证它的安全.





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