继承关系中方法的执行

当字段实际类型与声明类型不同时,方法的调用不同。

字段实际类型与所声明类型不同时,Override与Overload中方法的调用策略的不同。

Father f = new Son();

上述代码中,实际类型是Son,声明类型是Father

表面类型(声明类型):对象声明时的类型

实际类型:对象产生时的类型

例子1

 class COne {
        public void f() {
       	 System.out.println("COne.f");
        }
    }
 
    class CTwo extends COne{
	   public void f() {
		  System.out.println("CTwo.f");
       }  
    }

    class CThree {
		public void g(COne one) {
			System.out.println("g(Cone)");
			one.f();当用对象名.去使用方法的时候,调用的是实际类型的的方法
    	}

    	public void g(CTwo two) {
			System.out.println("g(Ctwo)");
			two.f();
        }
    }
    public class Main {
		public static void main(String[] args) {
			COne one = new CTwo(); //表面类型是COne,实际类型是CTwo
        	CThree three = new CThree();
			three.g(one);//当传参进来使用时,使用的是表面类型
        }
    }

输出:

 g(Cone)  

       CTwo.f


分析:表面类型是COne,实际类型是CTwo。

CThree类中使用了重载(Overload),Overload为静态多态,在编译阶段静态类型检查过程中决定了具体执行哪个方法,故其调用了其传入参数声明类型COne类的方法。

Java的方法中的参数传递是按值传递,引用所指向的表明类型的对象。

对象名.方法调用时使用的是实际类型。

子类CTwo中的f()方法重写了父类COne中的此方法,而最终执行结果是是调用的子类的方法,这说明方法的重写是动态

当one作为参数传入时是作为声明类型COne父类传入的,也说明了重载是静态的。

静态类型和声明类型是在编译期间就是可知的,而实际类型要等到运行期间才可知,

通过继承,子类拥有与父类同名的非私有的属性和方法,子类重新定义某个属性,在父类不会被覆盖,该属性的对象在编译时的类型为父类,运行时为子类。

对于对象调用运行时类型的方法便是出于对多态的考虑。

例子2

class A{
    int i=1;
    void say(){
        System.out.println(i);
    }
}
class B extends A{
    int i=2;
    void say(){
        System.out.println(i);
    }
}
public class Main{
    public static void main(String args[]) {
        A a=new B();
        System.out.println(a.i); //编译-- 父类 
        a.say();  //运行-- 子类 
    }
}

输出:

1

2

在动态运行过程中,JVM调用的方法为其实际类型所重写的方法。


例子3

class Base{
    void test() {
    System.out.println("Base.test()");
    }
}

public class Child extends Base {
    void test() {
    System.out.println("Child.test()");
}

static public void main(String[] a) {
    Child anObj = new Child();
    Base baseObj = (Base)anObj; //父类引用指向子类对象 子类对象赋给父类 真实对象是子类
    baseObj.test();
    }
}

输出:Child.test()

分析:子类对象向上转换成父类(子类对象赋值给父类对象)。

子类重写父类的方法,编译时为父类对象,运行时为子类对象。

  • 此时通过父类引用变量调用的方法是子类覆盖或继承父类的方法,不是父类的方法。
  • 此时通过父类引用变量无法调用子类特有的方法。

所以调用的是子类方法。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值