java:继承中子类和父类构造器的相关内容

在Java中,当父类的无参构造器被有参数的构造器覆盖时,子类创建对象时需在构造器中通过`super(参数)`指定调用父类的哪个构造器。否则,编译会出现错误。子类构造器执行前,总是先调用父类构造器,确保父类的初始化。若父类没有显式定义构造器,会有一个默认的无参构造器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.  首先, 子类必须调用父类的无参构造器,完成对父类的初始化
package com.hspedu.extend_;

public class Base { // 父类


    public Base(){  // 父类无参构造器
        System.out.println("父类无参构造器Base()被调用");
    }
}
package com.hspedu.extend_;

import com.hspedu.extend_.Base;

public class Sub extends Base {     //子类
    
    public Sub(){   // 子类无参构造器
        System.out.println("子类无参构造器Sub()被调用");
    }
}
运行后我们会发现,先调用了父类的无参构造器完成父类初始化,后才调用了子类的构造器

//  当子类对象创建时,不管使用子类的哪个构造器,默认情况下会先调用父类的无参构造器。
//  如果父类没有无参构造器,则必须在子类构造器中用super()去指定使用父类的哪个构造器去
//  完成对父类的初始化,否则编译无法通过
package com.hspedu.extend_;

public class Base { // 父类


//    public Base(){  // 父类无参构造器
//        System.out.println("父类无参构造器Base()被调用");
//    }

    public Base(int x){  // 父类中有参数的构造器,编写后会覆盖掉默认的无参构造器
        System.out.println("父类有参数的构造器Base(int x)被调用");
    }
}

然后我们将父类中的无参构造器屏蔽, 创建一个有参数的构造器,这时会覆盖掉其默认的无参构造器,当我们创建子类对象时,如果不加以说明,子类就无法调用默认的无参构造器从而编译错误。

### Java 中子父类传递参数的方法 在 Java 中,当创建一个子类的对象时,默认情况下会先调用父类的无参构造函数。然而,在实际开发中经常需要带参数来初始化父类中的属性。这可以通过显式地使用 `super` 关键字来完成。 #### 使用 super 调用父类构造函数 为了使子类能够向父类传递参数,可以在子类的构造函数里利用 `super()` 来指定要调用哪个版本的父类构造器,并提供相应的实参列表[^2]: ```java class Parent { String name; public Parent(String name) { // 父类中有参构造函数 this.name = name; System.out.println("Parent Constructor Called, Name is " + name); } } class Child extends Parent { public Child(String childName, String parentName) { super(parentName); // 显式的调用父类的有参构造函数 System.out.println("Child Constructor Called, Child's own property not initialized yet"); } } ``` 在这个例子中,每当实例化一个新的 `Child` 对象时,都会自动执行带有两个字符串参数的构造函数。该构造函数内部的第一条语句即为对父类构造函数的调用,它接收来自子类的一个额外参数用于设置父类的数据成员。 #### 注意事项 - 如果父类只有含参构造而没有无参构造,则子类必须在其构造函数内通过 `super(...)` 或者间接地经由其他方式确保能访问到合适的父类构造形式。 - 当定义了一个自定义构造函数之后,即使它是私有的或者是受保护级别的,编译器也不会再为你合成默认(无参)构造函数了;因此在这种情形下如果不主动声明任何构造函数的话,将会导致无法隐式调用父类构造的情况发生。 #### 完整示例程序 下面给出一段完整的代码片段展示上述概念的应用场景: ```java public class MainApp { static class Parent { private final int value; protected Parent(int v){ this.value = v; System.out.printf("Parent constructor called with %d\n",v); } @Override public String toString(){ return String.format("Value from Parent: %d",this.value); } } static class Child extends Parent{ private final double factor; public Child(double f,int pVal){ super(pVal); // 此处传入pVal作为父类构造函数的参数 this.factor=f; System.out.printf("Child constructor called with %.1f and inherited value of %s\n", f,new Parent(pVal)); } @Override public String toString(){ return String.format("%s * Factor=%.1f=%g",super.toString(),factor,value()*factor); } private float value(){return (float)this.factor*(int)(Math.random()*10);} } public static void main(String[] args) { new Child(2.789,45).toString(); } } ``` 此段代码展示了如何在一个继承体系结构中有效地让子类父类传递必要的配置信息以便于后者可以正常工作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值