黑马程序员——父类与子类的构造器

本文探讨了Java中子类构造函数如何隐式调用父类无参构造函数的现象,并展示了当父类只有带参数构造函数时,子类必须显式调用父类构造函数的情况。

-----------  android培训 java培训 、java学习型技术博客、期待与您交流! ------------


代码:

class Base{

   Base(){

       System.out.println("Base with no arg");

    }

}

 

class Test extends Base{

   Test(int v){

    }

 

   public static void main(String[] args) {

       Test a = new Test(3); 

    }

}

输出

Base with no arg

这里子类里面没有显式调用父类的构造函数,但是父类的构造还是被调用了,说明Java加载类的时候,会加载父类的无参数的构造函数

 

 

class Base{

   Base(int val){

       System.out.println("Base int");

    }

}

 

class Test extends Base{

   Test(int v){

    //如果这里不调用super(v) 是无法通过编译的

    }

 

   public static void main(String[] args) {

       Test a = new Test(3);

    }

}

<think>嗯,用户想了解Java中父类子类构造器的调用规则以及继承关系。好的,我需要先回忆一下相关的知识点,然后结合提供的引用内容来组织回答。首先,构造器在继承中的处理方式,我记得父类构造器不会被子类继承,所以在创建子类实例时,需要调用父类构造器来初始化父类部分。 根据引用[1],子类初始化时会隐式调用父类的无参构造器。如果父类没有无参构造器,必须在子类中用super显式调用,否则编译错误,这点在引用[3]里也提到了。所以需要强调父类有无无参构造器的情况下的处理方式。 然后,调用顺序应该是先父类构造器,再子类构造器。比如例子中的Father和Son类,先输出Father Function,再Son Function。这部分可以结合引用[1]的例子说明。 还有,子类构造器默认调用super(),也就是父类的无参构造器。如果父类只有有参构造器子类必须显式调用super(参数),否则会报错。引用[3]也指出这点,需要用户注意。 另外,用户可能对方法重写后的调用顺序有疑问,比如super.method()的使用,但这个问题主要关于构造器,所以暂时可以忽略引用[2]的内容,除非涉及到方法调用中的super,但构造器部分已经足够回答。 需要分步骤说明初始化过程:1. 子类构造器隐式或显式调用父类构造器;2. 父类构造器执行;3. 子类构造器继续执行。同时,如果有多个父类构造器,比如多层继承,需要说明调用链。 可能的问题点包括父类没有无参构造器时的处理,以及super必须放在子类构造器的第一行。这些都需要在回答中明确,并给出示例代码。 最后,生成相关问题时要围绕构造器调用规则、初始化顺序、super关键字的作用等方面提问,帮助用户进一步理解。</think>### Java父类子类构造器调用规则及初始化过程解析 #### 一、构造器调用规则 1. **父类构造器不会被子类继承** 子类无法直接继承父类的构造方法,但**初始化子类对象时,必须调用父类构造器**以完成父类成员的初始化[^1][^3]。 2. **隐式调用父类无参构造器** 若父类存在无参构造器子类构造器会**隐式调用`super()`**(即父类无参构造器),无需显式编写代码。例如: ```java class Father { Father() { System.out.println("Father Function"); } // 父类无参构造器 } class Son extends Father { Son() { System.out.println("Son Function"); } // 隐式调用super() } // 输出顺序:Father Function → Son Function ``` 3. **显式调用父类有参构造器** 若父类**没有无参构造器**,子类构造器必须**显式调用父类的有参构造器**,且必须放在子类构造器的第一行。例如: ```java class Father { Father(int param) { System.out.println("Father with param"); } } class Son extends Father { Son() { super(10); // 显式调用父类有参构造器 System.out.println("Son Function"); } } ``` 4. **多层继承的调用链** 构造器调用遵循**从最顶层父类子类逐层执行**的规则。例如: `Grandfather构造器 → Father构造器 → Son构造器`。 --- #### 二、初始化过程详解 1. **内存分配阶段** 为子类对象分配内存空间,包含父类子类定义的成员变量。 2. **父类构造器执行** 调用父类构造器初始化父类成员变量。若父类继承自其他类,继续向上递归调用。 3. **子类构造器执行** 父类初始化完成后,执行子类构造器的剩余代码。 --- #### 三、关键注意事项 1. **super关键字的限制** - 必须出现在子类构造器的**第一行** - 不可`this()`同时使用(二者均需占据第一行) 2. **默认构造器的陷阱** 若父类未显式定义无参构造器,且子类未显式调用父类有参构造器,会导致编译错误。例如: ```java class Father { Father(int x) {} // 父类只有有参构造器 } class Son extends Father { Son() {} // 编译错误:未调用super(参数) } ``` --- #### 四、典型场景示例 **场景1:隐式调用父类无参构造器** ```java class Animal { Animal() { System.out.println("Animal initialized"); } } class Dog extends Animal { Dog() { System.out.println("Dog initialized"); } } // 输出顺序:Animal initialized → Dog initialized ``` **场景2:显式调用父类有参构造器** ```java class Vehicle { Vehicle(String type) { System.out.println("Vehicle: " + type); } } class Car extends Vehicle { Car() { super("Sedan"); // 显式调用父类构造器 System.out.println("Car initialized"); } } // 输出顺序:Vehicle: Sedan → Car initialized ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值