首页 > 其他分享 >继承+super

继承+super

时间:2025-01-12 16:10:55浏览次数:1  
标签:无参 继承 构造 Person 父类 super public

2.继承

继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

◆extends的意思是“扩展”。子类是父类的扩展。

◆JAVA中类只有单继承,没有多继承!

父类Person

package com.oop.demo02;
//是学生、老师类的父类
//子类可以继承父类方法和属性(public)
/*
* public
* protected
* default  什么都没写 就是default这个
* private
* */
public class Person {
    public int legacy=10_0000_0000;//这里定义的是public的变量
    private  int estate=20_0000_0000;//这里定义的是私有属性,不给子类使用
    //注意这里的say方法是public修饰的
    public void say(){
        System.out.println("我说了一句话!");
    }
}

子类学生类 Student

package com.oop.demo02;
//学生继承了人  这个类  是person的子类/派生类
public class Student extends Person{
    //Person person;  //组合,暂时还不知道什么意思
}

子类教师类

package com.oop.demo02;
//老师类继承了 人这个类   是person的子类
public class Teacher extends Person {

}

启动类Application

package com.oop.demo02;
//启动类(包内包外都可以  import(包外))
//Demo02  面向对象 继承
//object类
//这是包外启动项  主要想测试下 import
//还有public 等关键字
//Crtl+H 打开结构树
//在java的类都默认直接或者间接继承Object类!
//java中只有单继承,没有多继承  一个儿子只能有一个爸爸,但是一个爸爸可以有多个儿子
public class Application {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.say();//这个方法是Student继承了人这个类的
        System.out.println(s1.legacy);//继承了父类的属性
        //System.out.println(s1.estate);//私有的不给子类用
        Teacher t1 = new Teacher();
        t1.say();//同理t1继承了人这个类的say方法
        System.out.println(s1.legacy);//继承了父类的属性
    }
}

◆继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等
◆继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示
◆子类和父类之间,从意义上讲应该具有"is a"的关系.

◆object类
◆super

父类Person

package com.oop.demo03;

public class Person {
 protected String name="巢安龙";
 private int age=20;
 protected void print(){
     System.out.println("Person");
 }
}

子类学生类Student

package com.oop.demo03;
//继承的的包内Demo03 的 Person类
public class Student extends Person {
public String name="胖呼呼";
 
public void test(String name){
   System.out.println(name); //打印传进来的形参的 name
     System.out.println(this.name);//打印实例化对象的 name
     System.out.println(super.name);//打印父类的 name
   }
 public void print(){
   System.out.println("Student");
   }
 public void print_new(String content){
   System.out.println(content);
     print();
     this.print();
     super.print();//调用父类的方法
   }
 }

子类教师类 Teacher

package com.oop.demo03;
//继承的的包内Demo03 的 Person类
public class Teacher extends Person{
public String name="longGe";
public void test(String name){
   System.out.println(name); //打印传进来的形参的 name
   System.out.println(this.name);//打印实例化对象的 name
     System.out.println(super.name);//打印父类的 name
   }
   }
 

应用类Application

package com.oop.demo03;//这里主要突出 继承super 的
//super 指代实例化对象的父类  可以调用父类的属性和方法(当然私有的private 无法被继承)
//this 指代当前实例化对象
public class Apllication {
public static void main(String[] args) {
  Student student = new Student();
   //super 调用父类的属性(private的不行)
     student.test("癞痢皮");
     Teacher teacher = new Teacher();
     teacher.test("chaoGe");//这两个方法名竟然可以一样
     //student.super//为什么在测试类里面用不了super 还是我的使用方法出了问题呢?
     //super 调用父类里面的方法! 看Student类里面的详细实现
     student.print_new("student_content");
   }
   }
 

输出结果:

癞痢皮
胖呼呼
巢安龙
chaoGe
longGe
巢安龙
student_content
Student
Student
Person

为什么在测试类里面用不了super 还是我的使用方法出了问题呢?

package com.oop.Demo03;//这里主要突出 继承super 的
//super 指代实例化对象的父类  可以调用父类的属性和方法(当然私有的private 无法被继承)
//this 指代当前实例化对象
public class Apllication {
 public static void main(String[] args) {
     Student student = new Student();
     //student.test("癞痢皮");
     //Teacher teacher = new Teacher();
     //teacher.test("chaoGe");//这两个方法名竟然可以一样
     student.super//为什么在测试类里面用不了super 还是我的使用方法出了问题呢?
 }
}

在你的代码中,super 是一个关键字,用于引用父类(超类)中的构造方法、属性和方法。在 Java 中,super 不能在实例化对象的类方法中直接使用,而是用于访问当前对象的父类成员。

为什么你无法在 Apllication 类中使用 super

  1. super 只能在 子类的实例方法中使用,目的是访问父类的成员(方法、变量、构造器等)。你不能在父类(如 Apllication 类)的 main 方法中直接使用 super,因为 main 方法是静态方法,它并不属于任何具体的实例对象。
  2. 如果你希望使用 super,你需要在 子类中编写方法,使用 super 来访问父类的成员。

使用 super 的正确方法:

  1. 父类和子类的关系:子类通过继承父类,可以访问父类的公开成员(publicprotected)以及父类提供的方法和构造器。private 成员是不能被继承的,因此 super 无法访问它们。
  2. super 用法示例
    • 在子类中,使用 super() 调用父类构造器。
    • 使用 super.属性super.方法 来调用父类的成员或方法。

代码示例

假设你有一个父类 Person,和一个子类 Student,你可以在子类中使用 super 来访问父类的成员。

父类 Person

package com.oop.Demo03;

public class Person {
    protected String name; // protected 使得子类可以访问
    protected int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void introduce() {
        System.out.println("我叫 " + name + ",年龄 " + age);
    }
}

子类 Student

package com.oop.Demo03;

public class Student extends Person {
    private String school;

    public Student(String name, int age, String school) {
        // 调用父类的构造方法
        super(name, age);//必须放在这个方法提第一行
        this.school = school;
    }

    public void introduce() {
        // 调用父类的 introduce 方法
        super.introduce();  // 访问父类的成员方法
        System.out.println("我来自 " + school);
    }
}

测试类 Application

package com.oop.Demo03;

public class Application {
    public static void main(String[] args) {
        Student student = new Student("张三", 20, "清华大学");
        student.introduce();
    }
}

解释:

  1. super(name, age):在 Student 的构造方法中,super 用来调用父类 Person 的构造方法,以初始化父类的 nameage 属性。
  2. super.introduce():在 Studentintroduce 方法中,通过 super.introduce() 调用父类 Personintroduce 方法。
  3. super 在子类中使用super 用于子类中访问父类的成员或构造方法,但不能在父类(如 Application 类)中使用。

你的错误:

你在 Application 类的 main 方法中尝试使用 super,这是不允许的。因为 super 是用来指代子类对象的父类成员的,所以它只能在子类的实例方法中使用。

1. 如果没有定义构造器,Java 会默认提供一个无参构造器

  • 正确,如果你没有定义任何构造器,Java 会自动提供一个无参构造器,且该构造器什么都不做。
public class Person {
    private String name;
    // Java 会自动提供如下无参构造器
    // public Person() { }
}

你可以通过以下方式创建对象:

Person person = new Person();  // 调用自动生成的无参构造器

1.1 如果没有显式写无参构造器,也能直接创建对象

  • 正确,如果你没有定义任何构造器,Java 会自动提供一个无参构造器。
  • 你可以直接用 new 创建对象,而不需要显式定义无参构造器。
public class Person {
    private String name;
    // 没有显式定义构造器,Java 会提供一个默认的无参构造器
}

Person person = new Person();  // 正常创建对象

1.2 如果你定义了有参构造器,就不会自动提供无参构造器

  • 正确,当你定义了有参构造器后,Java 不会再自动提供无参构造器。如果此时你希望使用无参构造器,你必须显式定义它,否则会报错。
public class Person {
    private String name;

    // 显式定义了有参构造器
    public Person(String name) {
        this.name = name;
    }
}

// 这会报错:因为没有无参构造器
Person person = new Person();  // 编译错误

如果你希望仍然能使用无参构造器来创建对象,就必须显式定义一个无参构造器:

public class Person {
    private String name;

    // 无参构造器
    public Person() {
        this.name = "默认名字";
    }

    // 有参构造器
    public Person(String name) {
        this.name = name;
    }
}

Person person1 = new Person();       // 使用无参构造器
Person person2 = new Person("张三");  // 使用有参构造器

1.3 子类创建对象时会默认先调用父类的构造器,默认调用父类的无参构造器

  • 正确当你创建一个子类对象时,Java 会默认调用父类的构造器。如果父类没有无参构造器,且你没有显式调用父类的有参构造器,就会报错。
  • 如果父类只有有参构造器,而没有无参构造器,子类的构造器必须显式调用父类的有参构造器。
public class Person {
    private String name;

    // 只有有参构造器
    public Person(String name) {
        this.name = name;
    }
}

public class Student extends Person {
    // 子类无参构造器
    public Student() {
        // 必须显式调用父类的有参构造器
        super("张三");  // 调用父类的有参构造器
    }
}

// 这样可以创建 Student 对象
Student student = new Student();  // 正常创建对象,调用了父类的有参构造器

如果你没有在子类构造器里显式调用父类的构造器,且父类没有无参构造器,就会编译错误。

总结:

  1. 如果你没有定义构造器:Java 会自动提供一个无参构造器。
  2. 如果你定义了有参构造器:Java 不会自动提供无参构造器。如果需要无参构造器,你必须显式定义。
  3. 如果子类创建对象时,父类没有无参构造器:Java 会默认调用父类的无参构造器。如果父类没有无参构造器,子类必须显式调用父类的有参构造器(super(参数))。
  4. 子类创建对象时,必须先调用父类构造器,否则会报错,特别是在父类没有无参构造器时,必须显式调用父类的有参构造器。

是不是在自己写类的时候最好显式加无参构造器

在自己编写类时,是否显式添加无参构造器通常取决于几个因素,特别是你希望如何使用这个类,以及它的继承关系。总体而言,在大多数情况下,显式地添加无参构造器是一个好习惯,尤其是在以下几种场景中:

1. 需要使用无参构造器时

如果你希望通过无参构造器创建对象,或者某些库和框架(如 Java 序列化、反射、Spring 等)需要无参构造器来实例化类,显式定义一个无参构造器就非常重要。例如:

  • 反射:有些框架或工具会通过反射来创建对象,这时需要有一个无参构造器。
  • 序列化和反序列化:Java 的序列化机制通常会要求类有一个无参构造器,因为反序列化时需要先创建对象然后再设置字段的值。

2. 继承关系中的构造器调用

如果你的类作为父类被继承,子类默认会调用父类的构造器。如果父类没有显式定义无参构造器,且子类没有显式调用父类的有参构造器,子类的构造器会报错。因此,在父类中定义无参构造器可以避免一些潜在的错误。

3. 给类添加默认行为或值

无参构造器通常用于设置类的默认状态,尤其是在没有外部输入的情况下。例如:

public class Person {
    private String name;
    private int age;

    // 无参构造器,设置默认值
    public Person() {
        this.name = "未知";
        this.age = 0;
    }

    // 有参构造器,允许外部设置值
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

在这个例子中,使用无参构造器会创建一个默认值的 Person 对象,而有参构造器可以根据需要设置特定的值。

4. 兼容性

如果你将这个类交给其他开发人员使用或集成到框架中,添加无参构造器会提供更高的兼容性。这样,无论是框架,还是其他开发人员都能更方便地创建对象。

5. 反序列化和 JSON 处理

在处理 JSON 时,比如使用 JacksonGson 等库,它们会使用无参构造器来创建对象,然后通过 setter 方法或字段直接填充数据。如果没有无参构造器,反序列化可能会失败。

6. 避免潜在问题

如果类没有无参构造器且又没有显式地在其他构造器中调用父类的构造器,子类可能会无法正确实例化。因此,明确地定义一个无参构造器可以避免这种潜在的错误。

7. 特殊情况:当你有复杂初始化逻辑时

如果你的类有一些复杂的初始化逻辑,而无参构造器的行为难以保证,可能需要避免使用无参构造器。例如,当类需要接收特定的依赖项(如数据库连接、外部服务等)时,最好使用有参构造器来确保类在创建时得到正确的初始化。

小结:是否显式添加无参构造器

  • 推荐做法在多数情况下,尤其是类有多个构造器时,显式添加无参构造器是一个好习惯。这样做不仅能提供更好的兼容性,还能避免继承时的构造器问题。
  • 例外情况如果类的构造过程非常复杂,或者你不希望允许无参实例化对象(比如不想创建空对象),则可以选择不定义无参构造器。

总之,虽然 Java 编译器会在某些情况下自动提供无参构造器,但为了明确控制对象创建过程,并提高代码的可维护性和兼容性,显式添加无参构造器是一个值得推荐的做法。

super注息点:
1.super调用父类的构造方法,必须在构造方法的第一个

2.super 必须只能出现在子类的方法或者构造方法中!

3、super和 this 不能同时用构造方法!
Vs this:

代表的对象不同:this: 本身调用者这个对象super:代表父类对象的应用

前提

this:没有继承也可以使用super:只能在继承条件才可以使用构造方法
this();本类的构造super():父类的构造!

继承中构造器执行顺序

父类 Person

package com.oop.demo04;

public class Person {
    private String name;

    //无参构造器 构造方法
   public Person() {
    System.out.println("Person无参构造执行了!");
    }
    //Person的有参构造器
    public Person(String name) {
        this.name = name;
    }
}

子类学生类 Student

package com.oop.demo04;

//继承的的包内Demo04 的 Person类
public class Student extends Person {
    private String name;
    //无参构造器  无参构造方法
    public Student() {
        //隐藏代码,可以不写的
        //super();//调用父类的构造器必须要在子类的第一行 所以如果父类定义了有参却没有定义无参 子类初始化就会报错
        //this("巢安龙");//调用本类的构造器(有参/无参) 本类的第一行

// 由于继承了父类 所以子类创建对象时调用了构造器,就会会默认调用父类的无参,如果无参没有初始化就会报错
//解决办法 手动添加无参构造  或者直接调用父类的有参构造(有的话)
        super();//这是直接调用父类的无参构造器 继承的话 这句是可以省略的 但是如果写了就得放在此方法体的第一行
        //super("perple's name");//调用父类的构造器也必须要在子类的第一行
        System.out.println("Student无参构造执行了!");
    }
    public Student(String name) {
        //这里父类没有无参构造器 得加一句 super(参数)父类的有参构造器(有的话)
        super("name");
        this.name=name;
    }
}

子类教师类 Teacher

package com.oop.demo04;

//继承的的包内Demo04 的 Person类
public class Teacher extends Person {

    public Teacher() {
        super();
    }

    public Teacher(String name) {
        super("name");
    }
}

启动类Application

package com.oop.demo04;//这里主要突出 继承super 的
//此软件包主要突出 super 对构造器的影响
//alt +insert 快捷插入构造器
public class Apllication {
    public static void main(String[] args) {
        Student student = new Student();//这里实例化Student类 调用其无参构造器,但是由于Student类继承了Person类,所以调用Student无参构造的时候也调用了Person的无参构造器

    }
}

输出结果:

Person无参构造执行了!
Student无参构造执行了!

注意点:

关键点:

  1. super() 关键字
    • 用于在子类构造器中调用父类构造器。
    • super() 调用父类的无参构造器,super(参数) 调用父类的有参构造器。
  2. 构造器调用顺序
    • 子类构造器首先调用父类构造器(无参或有参),然后执行子类构造器的内容。
    • super() 必须是子类构造器的第一行代码。
  3. 继承中的构造器
    • 如果父类没有无参构造器,子类必须显式调用父类的有参构造器。
    • 如果子类没有显式调用父类构造器,Java 会默认调用父类的无参构造器(前提是父类有无参构造器)还是那个问题,子类不用父类有参构造,会默认调用父类无参,此时如果父类有有参构造器又没有无参构造器,那就要么添加父类无参构造器,或者显式调用定义好的父类有参构造器
  4. 默认构造器
    • 如果子类没有定义构造器,Java 会提供一个默认的无参构造器,自动调用父类的无参构造器。
    • 如果父类没有无参构造器,则子类必须显式调用父类的有参构造器。

标签:无参,继承,构造,Person,父类,super,public
From: https://www.cnblogs.com/panghuhu-space/p/18667012

相关文章

  • Sigrity System SI SerialLink模式进行USB3.0协议仿真分析操作指导-SuperSpeed_Rx_Dev
    SigritySystemSISerialLink模式进行USB3.0协议仿真分析操作指导-SuperSpeed_Rx_DeviceSigritySystemSISerialLink模式提供了10个协议合规性检查工具模板,用户可以将根据实际应用替换模板中的SPICE文件,然后进行协议仿真分析,同时软件还提供了目标结果的模板MASK以及该协议......
  • Sigrity System SI SerialLink模式进行USB3.0协议仿真分析操作指导-SuperSpeed_Tx_Hos
    SigritySystemSISerialLink模式进行USB3.0协议仿真分析操作指导-SuperSpeed_Tx_HostSigritySystemSISerialLink模式提供了10个协议合规性检查工具模板,用户可以将根据实际应用替换模板中的SPICE文件,然后进行协议仿真分析,同时软件还提供了目标结果的模板MASK以及该协议需......
  • CSS选择器有哪些?哪些属性可以继承?
    CSS选择器有多种类型,包括但不限于以下几种:元素选择器:根据HTML元素的标签名来选择元素,例如p选择器会选择所有的段落元素。类选择器:使用.来选择具有特定类的元素,例如.my-class会选择所有类名为my-class的元素。ID选择器:使用#来选择具有特定ID的元素,例如#my-id会选择ID为my-......
  • 【论文阅读】Integrating single-cell multi-omics data through self-supervised clu
    论文地址:Integratingsingle-cellmulti-omicsdatathroughself-supervisedclustering-ScienceDirect代码地址:https://github.com/biomed-AI/scFPN摘要单细胞测序技术的进步使得个体细胞能够同时在多种组学层面进行测序,例如转录组学、表观基因组学和蛋白质组学。整合......
  • Sigrity System SI SerialLink模式进行USB3.0协议仿真分析操作指导-SuperSpeed_Tx_Dev
    SigritySystemSISerialLink模式进行USB3.0协议仿真分析操作指导-SuperSpeed_Tx_DeviceSigritySystemSISerialLink模式提供了10个协议合规性检查工具模板,用户可以将根据实际应用替换模板中的SPICE文件,然后进行协议仿真分析,同时软件还提供了目标结果的模板MASK以及该协议......
  • Java继承学习随记
    Java继承多态学习随记继承父类的private修饰无法调用子类构建时,先构建所继承的父类,再构建子类此处隐藏代码super();,默认调用父类的无参构建。此代码必须在构建器的任何一句代码前写。若想调用父类的有参构建,得在super();内写上参调用父类方法或参数使用super关键字,无......
  • uml 中 继承 实现 依赖 组合 等表示方法
    在UML(统一建模语言)中,不同的关系类型使用不同的箭头和线条来表示。以下是常见的UML关系及其对应的表示方法:1. 继承(Inheritance)表示:空心三角形箭头+实线方向:箭头指向父类(基类)说明:表示一个类继承自另一个类。示例: 复制[子类]——▷[父类]2. 实现......
  • JavaScript系列(16)--原型继承
    JavaScript原型继承......
  • 多继承背景下的调用逻辑【MRO】
    MROMRO(MethodResolutionOrder,方法解析顺序)是指在多继承情况下,Python解释器按照特定的顺序来查找和调用方法的规则。classA:passclassB:passclassC(A,B):passprint(C.__mro__)#输出:(<class'__main__.C'>,<class'__main__.A'>,<class......
  • C++泛型编程:类模版中成员函数的创建时机,类模版函数传参、类模版继承
    普通类的成员函数的话,在刚开始就创建出来了,但是类模版中的成员函数的话,只有在具体调用运行的时候才会被创建,可见以下代码例子:#include<iostream>usingnamespacestd;classpeople1{public: voidrun(){ cout<<"跑"<<endl; }};classcircle1{public: void......