创建子类对象时,父类构造函数中调用被子类重写的方法为什么调用的是子类的方法,而被子类重载的方法不会调用?

抽象薄雾
• 阅读 6601
public class Basic{
    public void add(int i)
    {
        System.out.println("Basic add");
    }
    
    public Basic()
    {
        add('a');
    }
}

public class A extends Basic{
    public void add(int i)
    {
        System.out.println("A add");
    }
}

public class B extends Basic{
    public void add(char i)
    {
        System.out.println("B add");
    }
}

public class Main{
    public static void main(String[] args)
    {
        A a = new A();
        B b = new B();
    }
}

问题:为什么创建A对象的时候父类会调用子类方法?
但是:创建B对象父类会调用父类的方法?

答案:
当子类被加载到内存方法区后,会继续加载父类到内存中。
如果,子类重写了父类的方法,子类的方法引用会指向子类的方法,否则子类的方法引用会指向父类的方法引用。
如果子类重载了父类方法,则子类重载方法引用还指向子类方法。
如果子类方法没有重写也没有重载父类方法,则方法引用会指向父类方法。

当子类对象创建时,会先行调用父类的构造方法(构造方法也是方法),虚拟机会在子类方法区寻找该方法并运行。
但是:由于java语言是静态多分派,动态单分派。其结果是当编译的时候,父类构造方法调用的方法的参数已经强制转换为符合父类方法的参数了。
上边代码在编译前已经转换为下面这个样子的了。

public class Basic{
    public void add(int i)
    {
        System.out.println("Basic add");
    }
    
    public Basic()
    {
        add((int)'a');
    }
}

public class A extends Basic{
    public void add(int i)
    {
        System.out.println("A add");
    }
}

public class B extends Basic{
    public void add(char i)
    {
        System.out.println("B add");
    }
}

public class Main{
    public static void main(String[] args)
    {
        A a = new A();
        B b = new B();
    }
}

看一下上边的代码,是不是恍然大悟?

更多文章:http://blog.gavinzh.com

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java中多态的实现机制
多态的概念:  简单来说就是事物在运行过程中存在的不同状态,即父类或接口定义的引用变量指向子类或具体实现类的实例对象。程序调用方法在运行期才进行动态绑定,而不是引用变量的类型中定义的方法。多态存在的前提:1、存在继承关系,子类继承父类;2、子类重写父类的方法;3、父类引用指向子类对象。具体实例:1、定义一个父类:Animal
Wesley13 Wesley13
3年前
java对象
子父类间的成员方法关系:      子类调用的时候,先用的是自己的,如果没有再使用父亲的。如果父亲没有,就使      用父亲的父亲的...,最后,如果没有,就报错。         当子类中有和父类一模一样的方法的时候,子类使用的是自己的。   这种现象被称为方法(覆盖,复写,)重写。方法重写:  
Wesley13 Wesley13
3年前
java向上转型和向下转型1
  在java继承体系中,认为父类(超类)在上层,子类在下层(派生类),向上转型就是把子类对象转成父类对象。1publicclassFather{2publicvoideat(){3System.out.println("我是父类的方法吃。。。。。");4}
Jacquelyn38 Jacquelyn38
4年前
你不可不知的JS面试题(第二期)
1、什么是继承?子类可以使用父类的所有功能,并且对功能进行扩展。新增方法改用方法(1)、ES6使用extends子类继承父类的方法。// 父类    class A        constructor(name)            this.name name;                getNa
Wesley13 Wesley13
3年前
C++中基类虚析构函数的作用及其原理分析
虚析构函数的理论前提是执行完子类的析构函数,那么父类的虚构函数必然会被执行。那么当用delete释放一个父类指针所实例化的子类对象时,如果没有定义虚析构函数,那么将只会调用父类的析构函数,而不会调用子类的虚构函数,导致内存的泄漏。故: 继承时,要养成的一个好习惯就是,基类析构函数中,加上virtual。知识背景     
Stella981 Stella981
3年前
Python3中的super()函数详解
关于Python3中的super()函数我们都知道,在Python3中子类在继承父类的时候,当子类中的方法与父类中的方法重名时,子类中的方法会覆盖父类中的方法,那么,如果我们想实现同时调用父类和子类中的同名方法,就需要使用到super()这个函数,用法为super().函数名()下面是一个例子:
Wesley13 Wesley13
3年前
Java多线程进阶干货(2)
问题1:子类可以调用父类的同步方法吗?/    一个同步方法可以调用另外一个同步方法,一个线程已经拥有某个对象的锁,  再次申请时,仍然会得到该对象的锁,也就是说synchronized获得的锁是可重入的   这里是继承中有可能发生的情形,子类调用父类的同步方法 /public class Test09 {    sy
Wesley13 Wesley13
3年前
C++多态学习之向下强制类型转换
向下强制类型转换在C中,基类(父类)指针可以指向派生类(子类)对象,因为派生类对象也是一个基类对象(但反过来不一样,基类对象不是一个派生类对象)。然而基类指针只能调用基类的成员函数,如果试图使用该指针调用仅在派生类中含有的成员函数(子类特有的,不是继承和重写父类的函数),将会产生编译错误。为了避免这一错误,就必须将基类指针转换成为派
Easter79 Easter79
3年前
Swift专题讲解十四——继承
Swift专题讲解十四——继承一、引言      Swift中,一个类可以从另一个类继承方法、属性、下标及其他特性。当一个类继承于另一个类时,这个类被称为子类,所继承的类被称为父类。在Swift中,继承是类区别于其他类型的主要特征。子类除了可以调用父类的属性,下标,方法外,其也可以对父类的属性,下标,方法进
Wesley13 Wesley13
3年前
Java面向对象浅谈
1\.方法重写override:参数列表必须完全与被重写方法的相同;返回类型必须完全与被重写方法的返回类型相同;访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。父类的成员方法只能被它的子类重写。声明
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
抽象薄雾
抽象薄雾
Lv1
是你吧,我能从很远很远的地方一眼认出你来
文章
2
粉丝
0
获赞
0