java继承向上转型和向下转型和动态绑定

1 概念: 把引用变量转化为子类类型,则成为向下转型。如果把引用变量转化为父类类型,则成为向上转型。 

Java代码
  1. public class Base {   
  2.     /**  
  3.      * 父类实例变量  
  4.      */  
  5.     String var = "baseVar";   
  6.     /**  
  7.      * 父类的静态变量  
  8.      */  
  9.     static String staticVar = "staticBaseVar";   
  10.   
  11.     /**  
  12.      * 父类实例方法  
  13.      */  
  14.     void method() {   
  15.         System.out.println("Base method");   
  16.     }   
  17.   
  18.     /**  
  19.      * 父类静态方法  
  20.      */  
  21.     static void staticMethod() {   
  22.         System.out.println("Base static Method");   
  23.     }   
  24. }   
  25.   
  26. public class Sub extends Base {   
  27.     /**  
  28.      * 子类的实例变量  
  29.      */  
  30.     String var = "subVar";   
  31.     /**  
  32.      * 子类的静态变量  
  33.      */  
  34.     static String staticVar = "staticSubVar";   
  35.   
  36.     // 覆盖父类的method()方法   
  37.     void method() {   
  38.         System.out.println("Sub static Method");   
  39.     }   
  40.   
  41.     String subVar = "var only belonging to Sub";   
  42.   
  43.     void subMethod() {   
  44.         System.out.println("Method only belonging to Sub");   
  45.     }   
  46.   
  47.     public static void main(String args[]) {   
  48.         // who 被声明为Base类型,引用Sub实例   
  49.         Base who = new Sub();   
  50.         System.out.println("who.var=" + who.var);// print:who.var=baseVar   
  51.         System.out.println("who.staticVar=" + who.staticVar);// print:who.staticVar=staticBaseVar   
  52.         who.method();// print:Sub static Metho   
  53.         // 这里为什么不打印Base method呢 这是java动态机制的表现,   
  54.         // 虽然who的类型是Base 但是 实际引用的是Sub类 new Sub()会在堆区分配内存空间   
  55.         // 当who.method()方法时,jvm会根据who持有的引用定位到堆区的Sub实例   
  56.         // 再根据Sub持有的引用 定位到方法区Sub类的类型信息 获得method的字节   
  57.         // 在当前环境下(上面代码所示)获得method的字节码,此时Sub类复写了Base的method的方法,   
  58.         // 获得method的字节码,直接执行method包含的指令,   
  59.         // 如果没有复写method方法 则去获得Base类的字节码 执行包含的指令(这个机制实现有待去研究有关资料)   
  60.         who.staticMethod();// print:Base static Method   
  61.   
  62.         // who.subVar="123";//编译错误   
  63.         // who.subMethod();//编译错误   
  64.         // 对于一个引用变量,java编译器按照它什么的类型来处理,这里who 的类型是Base类型的引用变量.不存在subVar   
  65.         // 和subMethod方法   
  66.         // 如果要访问Sub类成员,可以进行强制类型转换(向下转型)   
  67.         Sub sub = (Sub) who;   
  68.         sub.subVar = "23";   
  69.         sub.subMethod();   
  70.   
  71.         Base base2 = new Base();   
  72.         Sub sub2 = (Sub) base2;   
  73.         sub2.subMethod();   
  74.         // 编译通过 但是抛出ClassCastException   
  75.         // sub2实际引用的是Base实例   
  76.         // 对应一个引用类型的变量,运行时jvm按照它实际引用的对象来处理,假设上面能够通过,但是   
  77.         // 当我们sub2引用变量调用subMethod()方法时,我们看到在Base类中并没有subMethod方法。   
  78.         // 由此可见 ,子类对象可以向上转型为父类对象,但是父类对象不能转换为子类对象,父类拥有的成员子类   
  79.         // 子类肯定也有,而子类拥有的成员父类不一定有。上面就是一个例子。   
  80.   
  81.         // 在运行时环境中,通过引用类型变量来访问所引用的方法和属性时,java虚拟机采用如下绑定机制。   
  82.         // 1 实例方法与引用变量 实际引用的对象 的方法绑定 属于动态绑定.由运行时jvm动态决定的。   
  83.         // 2 静态方法与引用变了所声明的对象 的方法绑定 属于静态绑定 在编译阶段就已经做了绑定   
  84.         // 3 成员变量 (静态和实例)与引用变量所声明的类型的成员变量绑定属于静态绑定。   
  85.     }   
  86. }  
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 成员变量 (静态和实例)与引用变量所声明的类型的成员变量绑定属于静态绑定。
	}
}

 

 

Java代码
  1. abstract class A {   
  2.     abstract void method();   
  3.   
  4.     void test() {   
  5.         method();// 这里调用哪个类的method方法呢   
  6.     }   
  7. }   
  8.   
  9. public class B extends A {   
  10.     @Override  
  11.     void method() {   
  12.         System.out.println("B method");   
  13.     }   
  14.   
  15.     public static void main(String[] args) {   
  16.         new B().test(); // print:B method   
  17.         // 方法test()在父类A中定义,它调用了方法method   
  18.         // 但是method在A中是抽象的 但是仍然可以调用   
  19.         // 因为在运行时环境中jvm会执行B的实例的method方法   
  20.         // 一个实例所属的类肯定是实现了父类中所有的抽象方法   
  21.     }   
  22. }  
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方法
		// 一个实例所属的类肯定是实现了父类中所有的抽象方法
	}
}

 

 

Java代码
  1. class A {   
  2.     void method() {   
  3.         System.out.println("A method");   
  4.     };   
  5.   
  6.     void test() {   
  7.         method();// 这里调用哪个类的method方法呢   
  8.     }   
  9. }   
  10.   
  11. public class B extends A {   
  12.   
  13.     @Override  
  14.     void method() {   
  15.         System.out.println("B method");   
  16.     }   
  17.   
  18.     public static void main(String[] args) {   
  19.         //new B().test(); // print:B method   
  20.         // 方法test()在父类A中定义,它调用了方法method   
  21.         // 但是method在A中是抽象的 但是仍然可以调用   
  22.         // 因为在运行时环境中jvm会执行B的实例的method方法   
  23.         // 一个实例所属的类肯定是实现了父类中所有的抽象方法   
  24.        
  25.         new A().test();   
  26.         new B().test();   
  27.         //test()方法在A类中定义,它调用了method()方法,和上面的例子的区别是父类A的method方法   
  28.            
  29.         //不是抽象的,但是通过new B().test()执行的仍然是子类B的method方法,由此可见   
  30.         //在运行时环境中,当通过B类的实例去调用一系列的实例方法(包括一个方法调用另外一个方法)   
  31.         //将优先和B类本身包含的实例方法动态绑定,如果没有这个实例方法,才会从父类A中继承来的   
  32.         //实例方法动态绑定。    
  33.     }   
  34. }
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
向上转型是指将一个子类对象赋值给父类类型的变量,通过向上转型可以实现继承的多态性。多态性是指同一类型的对象在不同情况下表现出不同的行为。在向上转型中,父类对象可以引用子类对象,但只能调用父类中定义的方法和属性。这样做的好处是可以提高代码的灵活性和可复用性。通过向上转型,可以实现对父类对象的统一管理,只需要一个父类类型的引用变量就可以操作不同子类的对象,这样可以避免编写大量重复的代码。同时,向上转型还可以实现动态绑定,即在运行时根据对象的实际类型来确定调用哪个类的方法。这样可以实现不同子类的不同行为,提高了程序的扩展性和可维护性。因此,继承的多态性通过向上转型可以实现动态绑定和统一管理不同子类对象的优势。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [从向上转型走进java多态性](https://blog.csdn.net/daocaowuwu/article/details/121713221)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Day10 Java多态性继承关系中'向上转型'和'向下转型(还原)'的演示例子与作用及规则的详解.](https://blog.csdn.net/chinatopno1/article/details/103376577)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值