【Java 基础】引用型数组、Java 继承、super 关键字详解

在这里插入图片描述

Java 零基础入门到精通专栏持续更新中。通过本专栏你将学习到 Java 从入门进阶再到实战的全套完整内容,所有内容均将集中于此专栏。无论是初学者还是有经验的开发人员,都可从本专栏获益。


订阅专栏后添加我微信或者进交流群,进群可找我领取 前端/Java/大数据/Python/低代码/云原生 等全套视频课程,同时共同探讨问题、携手共进~


一、引用类型数组

在前面已经讲解过,数组分为基本类型数组和引用类型数组,我们通过代码来看一下两者的区别。

//基本类型数组
int[] a = new int[3];
double[] b = new double[3];

//引用类型数组 
Student[] stu = new Student[3];

int 、double 都是基本数据类型,那么对应的数组即基本类型数组,数组中的每一个元素都是其对应的数据类型。而在引用类型数组中我们使用的是某个类,这里的 Student 就是指一个类。 该语句意为:声明 Student 型数组,包含三个元素,每个元素都是 Student 型,默认值为 null。

声明任意数组时,中括号 [ ] 之前是什么型,数组的元素也就是什么型。

这两种数组类型的赋值方法是不同的,现在演示为数组的第一个元素赋值;

//基本类型数组
int[] a = new int[3];
a[0] = 100; //为数组中的第一个元素赋值

//引用类型数组
Student[] stu = new Student[3];
stu[0] = ?;

可以看到,这里的基本类型数组为 int 型,所以可直接为其元素赋值 int 型数据。而引用类型数组中的元素并不是基本类型数据,无法直接赋值,那么赋值方法应该是这样的:

//为引用类型数组中的元素赋值
Student[] stu = new Student[3];
stu[0] = new Student("zhangsan",24,"山西太原"); //学生1
stu[1] = new Student("lisi",25,"北京东城"); //学生2
stu[2] = new Student("wangwu",26,"陕西延安"); //学生3

这两种类型数组的元素的访问方法也是不同的。基本类型数组可直接使用 数组名[下标] 访问,而当我们要访问引用类型数组中的某个元素时,直接写 数组名[下标] 是错误的,正确的访问方式为 数组名[下标].属性

//访问引用数组中的元素
System.out.println(stu[0].name); //输出学生1的名字:zhangsan
System.out.println(stu[0].age); //输出学生1的年龄:24
System.out.println(stu[1].name); //输出学生2的名字:lisi
stu[0].age = 30; //修改学生1的年龄为30
stu[2].方法名(); //学生3调用某个方法

二、继承(extends)

“继承”顾名思义就是一些东西可以直接使用,而不用自己创建。在 Java 语言中这是一个非常重要的概念,它的最大意义就是提高代码的复用性,当有多个类需要使用相同的属性和方法时,将这些相同的内容抽取到单独的一个类中,那么多个类就无需再定义这些属性和行为,只要继承那一个类即可。

继承使用到的关键字为 extends,如下我们先定义一个 Person 类,包含姓名(name)、年龄(age)、地址(address) 三个属性,吃饭(eat())、睡觉(sleep()) 两个方法。然后再定义学生类(Student) 和教师类(Teacher) 来继承 Person 类。

class Person{
    
    
    String name;
    int age;
    String address;
    void eat(){
    
    }
    void sleep(){
    
    }
}

//定义学生类 继承Person
class Student extends Person{
    
    
    String stuId;
    void study(){
    
    }
}

//定义教师类 继承Person
class Teacher extends Person{
    
    
    double salary;
    void teach(){
    
    }
}

当使用 extends 关键字继承之后,学生类和教师类中的任何一个成员都可以直接访问自己类中的属性和方法以及 Peron 类中的各项属性和方法。

class Person{
    
    
    String name;
    int age;
    String address;
    void eat(){
    
    }
    void sleep(){
    
    }
}

//定义学生类 继承Person
class Student extends Person{
    
    
    String stuId;
    void study(){
    
    }
}
Student zhangsan = new Student(); //定义学生类的成员-zhangsan
//zhangsan可直接访问学生类和Person类中的属性和方法
zhangsan.stuId = "";
zhangsan.study();
zhangsan.name = "";
zhangsan.age = ;
zhangsan.eat();

//定义教师类 继承Person
class Teacher extends Person{
    
    
    double salary;
    void teach(){
    
    }
}
Teacher laoshi = new Student(); //定义教师类的成员-laoshi
//laoshi可直接访问教师类和Person类中的属性和方法
laoshi.salary = "";
laoshi.teach();
laoshi.name = "";
laoshi.age = ;
laoshi.eat();

在本案例中我们一共定义了三个类,其中被继承的类 Person 称为 父类/超类,继承父类的 Student 类和 Teacher 类称为 子类/派生类。父类中包含的是共有的属性和方法,子类中包含的是特有的属性和方法。子类可访问自己以及父类的属性和方法,但父类不可访问子类的属性和方法。此外继承还包含几个特性:

  1. 单一继承,一个父类可以有多个子类,但一个子类只能继承于一个父类;
  2. 传递性,代码如下;
  3. 构造子类之前必须先构造父类
class A{
    
     //类A仅可访问a
    int a;
}

class B extends A{
    
     //类B可访问b、a
    int b;
}

class C extends B{
    
     //类C可访问c、b、a
    int c;
}

三、super 关键字

注意区分 super 和 this:

  • super 指代当前对象的父类对象
  • this 指代当前对象

super 关键字指代当前对象的父类对象。它是这样使用的:

  • super.成员变量名 - 访问父类的成员变量
  • super.方法名() - 访问父类的方法
  • super() - 调用父类的构造方法

这里我们重点讲解 super() 的使用。在上一节已经知道,继承的特性是构造子类之前必须先构造父类,针对此特性 Java 有着明确的执行机制:在子类的构造方法中,若没有调用父类的构造方法,则默认使用 super() 调用父类无参构造方法

如下案例,我们创建父类 Aoo 和子类 Boo 并包含各自的构造方法,Boo 继承 Aoo;

public class Super {
    
    
    public static void main(String[] args) {
    
    
        Boo o = new Boo(); //创建Boo类下的对象o
    }
}
//父类A
class Aoo{
    
    
    Aoo(){
    
    
        System.out.println("父类构造方法");
    }
}
//子类B
class Boo extends Aoo{
    
    
    Boo(){
    
    
        System.out.println("子类构造方法");
    }
}

然后在 main 方法中创建子类 Boo 下的对象 o,运行程序;

在这里插入图片描述
按照正常的程序执行顺序,对象 o 是子类 Boo下的,那么运行程序后先执行的肯定是 Boo 的构造方法,即应该输出“子类构造方法”字样。但结果先执行的却是父类中的构造方法,然后才是子类中的构造方法。

这正是因为 Java 继承中 构造子类之前必须先构造父类 的特性,子类 Boo 中没有调用父类 Aoo 的构造方法,所以这里默认使用 super() 来调用父类构造方法;子类 Boo 的完整代码实际上是这样的:

//子类B
class Boo extends Aoo{
    
    
    Boo(){
    
    
    	super(); //该语句默认存在,调用父类无参构造方法
        System.out.println("子类构造方法");
    }
}

这也就导致了该程序的执行顺序为先执行 super(),输出“父类构造方法”,再执行 System.out.println("子类构造方法");,输出“子类构造方法”。

那如果子类中自己调用了父类的构造方法,又是怎样执行呢?

若子类中已调用父类构造方法,则不再默认提供 super() 语句;

public class Super {
    
    
    public static void main(String[] args) {
    
    
        Boo o = new Boo(); //创建Boo类下的对象o
    }
}
//父类A
class Aoo{
    
    
    Aoo(int a){
    
    
        System.out.println(a);
    }
}
//子类B
class Boo extends Aoo{
    
    
    Boo(){
    
    
        super(5); //子类自己调用超类构造方法
    }
}

程序运行结果如下:

在这里插入图片描述

四、本期推荐

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_53072519/article/details/130440391