zoukankan      html  css  js  c++  java
  • java继承向上转型和向下转型和动态绑定

    转载自:http://blog.csdn.net/hephec/article/details/28239399
    概念: 把引用变量转化为子类类型,则成为向下转型。如果把引用变量转化为父类类型,则成为向上转型。

    public class Base {   
        /**  
         * 父类实例变量  
         */  
        String var = "baseVar";   
        /**  
         * 父类的静态变量  
         */  
        static String staticVar = "staticBaseVar";   
    
        /**  
         * 父类实例方法  
         */  
        void method() {   
            System.out.println("Base method");   
        }   
    
        /**  
         * 父类静态方法  
         */  
        static void staticMethod() {   
            System.out.println("Base static Method");   
        }   
    }   
    
    public class Sub extends Base {   
        /**  
         * 子类的实例变量  
         */  
        String var = "subVar";   
        /**  
         * 子类的静态变量  
         */  
        static String staticVar = "staticSubVar";   
    
        // 覆盖父类的method()方法   
        void method() {   
            System.out.println("Sub static Method");   
        }   
    
        String subVar = "var only belonging to Sub";   
    
        void subMethod() {   
            System.out.println("Method only belonging to Sub");   
        }   
    
        public static void main(String args[]) {   
            // who 被声明为Base类型,引用Sub实例   
            Base who = new Sub();   
            System.out.println("who.var=" + who.var);// print:who.var=baseVar   
            System.out.println("who.staticVar=" + who.staticVar);// print:who.staticVar=staticBaseVar   
            who.method();// print:Sub static Metho   
            // 这里为什么不打印Base method呢 这是java动态机制的表现,   
            // 虽然who的类型是Base 但是 实际引用的是Sub类 new Sub()会在堆区分配内存空间   
            // 当who.method()方法时,jvm会根据who持有的引用定位到堆区的Sub实例   
            // 再根据Sub持有的引用 定位到方法区Sub类的类型信息 获得method的字节   
            // 在当前环境下(上面代码所示)获得method的字节码,此时Sub类复写了Base的method的方法,   
            // 获得method的字节码,直接执行method包含的指令,   
            // 如果没有复写method方法 则去获得Base类的字节码 执行包含的指令(这个机制实现有待去研究有关资料)   
            who.staticMethod();// print:Base static Method   
    
            // who.subVar="123";//编译错误   
            // who.subMethod();//编译错误   
            // 对于一个引用变量,java编译器按照它什么的类型来处理,这里who 的类型是Base类型的引用变量.不存在subVar   
            // 和subMethod方法   
            // 如果要访问Sub类成员,可以进行强制类型转换(向下转型)   
            Sub sub = (Sub) who;   
            sub.subVar = "23";   
            sub.subMethod();   
    
            Base base2 = new Base();   
            Sub sub2 = (Sub) base2;   
            sub2.subMethod();   
            // 编译通过 但是抛出ClassCastException   
            // sub2实际引用的是Base实例   
            // 对应一个引用类型的变量,运行时jvm按照它实际引用的对象来处理,假设上面能够通过,但是   
            // 当我们sub2引用变量调用subMethod()方法时,我们看到在Base类中并没有subMethod方法。   
            // 由此可见 ,子类对象可以向上转型为父类对象,但是父类对象不能转换为子类对象,父类拥有的成员子类   
            // 子类肯定也有,而子类拥有的成员父类不一定有。上面就是一个例子。   
    
            // 在运行时环境中,通过引用类型变量来访问所引用的方法和属性时,java虚拟机采用如下绑定机制。   
            // 1 实例方法与引用变量 实际引用的对象 的方法绑定 属于动态绑定.由运行时jvm动态决定的。   
            // 2 静态方法与引用变了所声明的对象 的方法绑定 属于静态绑定 在编译阶段就已经做了绑定   
            // 3 成员变量 (静态和实例)与引用变量所声明的类型的成员变量绑定属于静态绑定。   
        }   
    }  
    public class Base {   
        /**  
         * 父类实例变量  
         */  
        String var = "baseVar";   
        /**  
         * 父类的静态变量  
         */  
        static String staticVar = "staticBaseVar";   
    
        /**  
         * 父类实例方法  
         */  
        void method() {   
            System.out.println("Base method");   
        }   
    
        /**  
         * 父类静态方法  
         */  
        static void staticMethod() {   
            System.out.println("Base static Method");   
        }   
    }   
    
    public class Sub extends Base {   
        /**  
         * 子类的实例变量  
         */  
        String var = "subVar";   
        /**  
         * 子类的静态变量  
         */  
        static String staticVar = "staticSubVar";   
    
        // 覆盖父类的method()方法   
        void method() {   
            System.out.println("Sub static Method");   
        }   
    
        String subVar = "var only belonging to Sub";   
    
        void subMethod() {   
            System.out.println("Method only belonging to Sub");   
        }   
    
        public static void main(String args[]) {   
            // who 被声明为Base类型,引用Sub实例   
            Base who = new Sub();   
            System.out.println("who.var=" + who.var);// print:who.var=baseVar   
            System.out.println("who.staticVar=" + who.staticVar);// print:who.staticVar=staticBaseVar   
            who.method();// print:Sub static Metho   
            // 这里为什么不打印Base method呢 这是java动态机制的表现,   
            // 虽然who的类型是Base 但是 实际引用的是Sub类 new Sub()会在堆区分配内存空间   
            // 当who.method()方法时,jvm会根据who持有的引用定位到堆区的Sub实例   
            // 再根据Sub持有的引用 定位到方法区Sub类的类型信息 获得method的字节   
            // 在当前环境下(上面代码所示)获得method的字节码,此时Sub类复写了Base的method的方法,   
            // 获得method的字节码,直接执行method包含的指令,   
            // 如果没有复写method方法 则去获得Base类的字节码 执行包含的指令(这个机制实现有待去研究有关资料)   
            who.staticMethod();// print:Base static Method   
    
            // who.subVar="123";//编译错误   
            // who.subMethod();//编译错误   
            // 对于一个引用变量,java编译器按照它什么的类型来处理,这里who 的类型是Base类型的引用变量.不存在subVar   
            // 和subMethod方法   
            // 如果要访问Sub类成员,可以进行强制类型转换(向下转型)   
            Sub sub = (Sub) who;   
            sub.subVar = "23";   
            sub.subMethod();   
    
            Base base2 = new Base();   
            Sub sub2 = (Sub) base2;   
            sub2.subMethod();   
            // 编译通过 但是抛出ClassCastException   
            // sub2实际引用的是Base实例   
            // 对应一个引用类型的变量,运行时jvm按照它实际引用的对象来处理,假设上面能够通过,但是   
            // 当我们sub2引用变量调用subMethod()方法时,我们看到在Base类中并没有subMethod方法。   
            // 由此可见 ,子类对象可以向上转型为父类对象,但是父类对象不能转换为子类对象,父类拥有的成员子类   
            // 子类肯定也有,而子类拥有的成员父类不一定有。上面就是一个例子。   
    
            // 在运行时环境中,通过引用类型变量来访问所引用的方法和属性时,java虚拟机采用如下绑定机制。   
            // 1 实例方法与引用变量 实际引用的对象 的方法绑定 属于动态绑定.由运行时jvm动态决定的。   
            // 2 静态方法与引用变了所声明的对象 的方法绑定 属于静态绑定 在编译阶段就已经做了绑定   
            // 3 成员变量 (静态和实例)与引用变量所声明的类型的成员变量绑定属于静态绑定。   
        }   
    }  
    public class Base {   
        /**  
         * 父类实例变量  
         */  
        String var = "baseVar";   
        /**  
         * 父类的静态变量  
         */  
        static String staticVar = "staticBaseVar";   
    
        /**  
         * 父类实例方法  
         */  
        void method() {   
            System.out.println("Base method");   
        }   
    
        /**  
         * 父类静态方法  
         */  
        static void staticMethod() {   
            System.out.println("Base static Method");   
        }   
    }   
    
    public class Sub extends Base {   
        /**  
         * 子类的实例变量  
         */  
        String var = "subVar";   
        /**  
         * 子类的静态变量  
         */  
        static String staticVar = "staticSubVar";   
    
        // 覆盖父类的method()方法   
        void method() {   
            System.out.println("Sub static Method");   
        }   
    
        String subVar = "var only belonging to Sub";   
    
        void subMethod() {   
            System.out.println("Method only belonging to Sub");   
        }   
    
        public static void main(String args[]) {   
            // who 被声明为Base类型,引用Sub实例   
            Base who = new Sub();   
            System.out.println("who.var=" + who.var);// print:who.var=baseVar   
            System.out.println("who.staticVar=" + who.staticVar);// print:who.staticVar=staticBaseVar   
            who.method();// print:Sub static Metho   
            // 这里为什么不打印Base method呢 这是java动态机制的表现,   
            // 虽然who的类型是Base 但是 实际引用的是Sub类 new Sub()会在堆区分配内存空间   
            // 当who.method()方法时,jvm会根据who持有的引用定位到堆区的Sub实例   
            // 再根据Sub持有的引用 定位到方法区Sub类的类型信息 获得method的字节   
            // 在当前环境下(上面代码所示)获得method的字节码,此时Sub类复写了Base的method的方法,   
            // 获得method的字节码,直接执行method包含的指令,   
            // 如果没有复写method方法 则去获得Base类的字节码 执行包含的指令(这个机制实现有待去研究有关资料)   
            who.staticMethod();// print:Base static Method   
    
            // who.subVar="123";//编译错误   
            // who.subMethod();//编译错误   
            // 对于一个引用变量,java编译器按照它什么的类型来处理,这里who 的类型是Base类型的引用变量.不存在subVar   
            // 和subMethod方法   
            // 如果要访问Sub类成员,可以进行强制类型转换(向下转型)   
            Sub sub = (Sub) who;   
            sub.subVar = "23";   
            sub.subMethod();   
    
            Base base2 = new Base();   
            Sub sub2 = (Sub) base2;   
            sub2.subMethod();   
            // 编译通过 但是抛出ClassCastException   
            // sub2实际引用的是Base实例   
            // 对应一个引用类型的变量,运行时jvm按照它实际引用的对象来处理,假设上面能够通过,但是   
            // 当我们sub2引用变量调用subMethod()方法时,我们看到在Base类中并没有subMethod方法。   
            // 由此可见 ,子类对象可以向上转型为父类对象,但是父类对象不能转换为子类对象,父类拥有的成员子类   
            // 子类肯定也有,而子类拥有的成员父类不一定有。上面就是一个例子。   
    
            // 在运行时环境中,通过引用类型变量来访问所引用的方法和属性时,java虚拟机采用如下绑定机制。   
            // 1 实例方法与引用变量 实际引用的对象 的方法绑定 属于动态绑定.由运行时jvm动态决定的。   
            // 2 静态方法与引用变了所声明的对象 的方法绑定 属于静态绑定 在编译阶段就已经做了绑定   
            // 3 成员变量 (静态和实例)与引用变量所声明的类型的成员变量绑定属于静态绑定。   
        }   
    }  
    abstract class A {   
        abstract void method();   
    
        void test() {   
            method();// 这里调用哪个类的method方法呢   
        }   
    }   
    
    public class B extends A {   
        @Override  
        void method() {   
            System.out.println("B method");   
        }   
    
        public static void main(String[] args) {   
            new B().test(); // print:B method   
            // 方法test()在父类A中定义,它调用了方法method   
            // 但是method在A中是抽象的 但是仍然可以调用   
            // 因为在运行时环境中jvm会执行B的实例的method方法   
            // 一个实例所属的类肯定是实现了父类中所有的抽象方法   
        }   
    }  
    abstract class A {   
        abstract void method();   
    
        void test() {   
            method();// 这里调用哪个类的method方法呢   
        }   
    }   
    
    public class B extends A {   
        @Override  
        void method() {   
            System.out.println("B method");   
        }   
    
        public static void main(String[] args) {   
            new B().test(); // print:B method   
            // 方法test()在父类A中定义,它调用了方法method   
            // 但是method在A中是抽象的 但是仍然可以调用   
            // 因为在运行时环境中jvm会执行B的实例的method方法   
            // 一个实例所属的类肯定是实现了父类中所有的抽象方法   
        }   
    }  
    class A {   
        void method() {   
            System.out.println("A method");   
        };   
    
        void test() {   
            method();// 这里调用哪个类的method方法呢   
        }   
    }   
    
    public class B extends A {   
    
        @Override  
        void method() {   
            System.out.println("B method");   
        }   
    
        public static void main(String[] args) {   
            //new B().test(); // print:B method   
            // 方法test()在父类A中定义,它调用了方法method   
            // 但是method在A中是抽象的 但是仍然可以调用   
            // 因为在运行时环境中jvm会执行B的实例的method方法   
            // 一个实例所属的类肯定是实现了父类中所有的抽象方法   
    
            new A().test();   
            new B().test();   
            //test()方法在A类中定义,它调用了method()方法,和上面的例子的区别是父类A的method方法   
    
            //不是抽象的,但是通过new B().test()执行的仍然是子类B的method方法,由此可见   
            //在运行时环境中,当通过B类的实例去调用一系列的实例方法(包括一个方法调用另外一个方法)   
            //将优先和B类本身包含的实例方法动态绑定,如果没有这个实例方法,才会从父类A中继承来的   
            //实例方法动态绑定。    
        }   
    }
  • 相关阅读:
    如何使用SAP Intelligent Robotic Process Automation自动操作Excel
    OpenSAML 使用引导 IV: 安全特性
    Spring Cloud Zuul 网关使用与 OAuth2.0 认证授权服务
    微服务架构集大成者—Spring Cloud (转载)
    Spring Cloud Eureka 服务注册列表显示 IP 配置问题
    使用 Notification API 开启浏览器桌面提醒
    SignalR 中使用 MessagePack 序列化提高 WebSocket 通信性能
    配置 Nginx 的目录浏览功能
    关于 Nginx 配置 WebSocket 400 问题
    Migrate from ASP.NET Core 2.0 to 2.1
  • 原文地址:https://www.cnblogs.com/wangqilong/p/9417573.html
Copyright © 2011-2022 走看看