你一定要学会的Java语法 -- 【继承】

简介: 你一定要学会的Java语法 -- 【继承】

书接上回,我们已经学完了类和对象,今天内容可能有一点难,相信自己能跨过这道坎。



一. 继承

1.什么是继承

   看字面意思,让我们想到了电视剧中的那些大户人家,家族的后代,会继承家族的资产。那问题来了,java中的继承是什么呢 ?请看下文,让我们来揭开他的神秘面纱。

2. 继承的概念

继承机制 :是面向对象程序设计使代码可以复用的重要手段,主要解决了:共性的抽取,来实现代码的复用

什么时候要用继承,该怎么用呢?

3. 继承的语法

在java中如果要表示类之间的继承关系,需要借助extends 关键字,具体实现如下。

如果说我们要描述,猫和狗,它们都是一种动物,肯定会有共同特点。借助继承我们可以写出如下代码。

class Animal{
    public String name;
    public int age;
    public String color;
    public void eat(){
        System.out.println(this.name+" 正在吃饭....");
    }
    public void sleep(){
        System.out.println(this.name+" 正在睡觉....");
    }
}
class Dog extends Animal{
    public void bark(){
        System.out.println(this.name+" 正在汪汪叫....");
    }
}
class Cat extends Animal{
    public void mew(){
        System.out.println(this.name+" 正在喵喵叫....");
    }
}
public class test {
    public static void main(String[] args) {
        Dog dog = new Dog();  
// dog类中并没有定义任何成员变量,name和age属性肯定是从父类Animal中继承下来的
        dog.name = "旺财";
        dog.eat();
        dog.sleep();
        dog.bark();
        System.out.println("=======");
        Cat cat = new Cat();
        cat.name = "花花";
        cat.eat();
        cat.sleep();
        cat.mew();
    }
}

运行结果:

通过运行结果我们发现,我们根本就没有在Dog这个类里面定义name,age,但是可以访问,原因就是这些都是从Animal这个类当中继承下来的。

注意:

  • 1. 子类会将父类中的成员变量或者成员方法继承到子类中了
  • 2. 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了

 上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类或超类,Dog和Cat可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可

【结论】:子类继承了父类之后,子类就可以使用父类的成员变量和成员方法。 通过代码和图片能看出继承最大的作用就是:实现代码复用

4.父类成员访问

大家都知道,在继承体系中子类将父类的方法字段继承下来,子类能直接访问父类,那子类和父类的名字一样呢?

子类和父类成员变量同名

class Base{
    public int a = 1;
    public int b = 2;
}
class Derived extends Base{
    public int a = 10;
    public int b = 20;
    public void print(){
        System.out.println(a);
        System.out.println(b);
    }
}
public class Main {
    public static void main(String[] args) {
         Derived derived = new Derived();
         derived.print();
    }
}

运行结果:

子类和父类成员方法同名

class methodA{
    public void print(){
        System.out.println("父类的print方法");
    }
}
class methodB extends methodA{
    public void print(){
        System.out.println("子类的print方法");
    }
}
public class test1 {
    public static void main(String[] args) {
         methodB methodB = new methodB();
         methodB.print();
    }
}

运行结果:

【总结】:成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类找,父类也没有就报错。

那问题是,如果我们想访问父类的成员呢?

5.super关键字

在有些场景下,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成

员时,该如何操作?直接访问是无法做到的,Java提供了super关键字,该关键字主要作用:在子类方法中访问父类的成员。

class Base{
    public int a = 1;
    public int b = 2;
}
class Derived extends Base{
    public int a = 10;
    public int b = 20;
    public void print(){
        System.out.println(super.a);
        System.out.println(super.b);
    }
}
public class Main {
    public static void main(String[] args) {
         Derived derived = new Derived();
         derived.print();
    }
}

运行结果:

在子类中,如果想要明确访问父类中的成员是,借助super关键字即可。

【注意事项】

  • 1.只能在非静态方法中使用
  • 2.在子类方法中,访问父类的成员方法和变量。

6.子类构造方法  

 子类对象构造时,需要先调用父类的构造方法,然后执行子类的构造方法(可以理解成先有父后有子)。

运行结果:

一个小栗子

class Animal{
    public String name;
    public int age;
    public void eat(){
        System.out.println(this.name+" 正在吃饭....");
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
class Dog extends Animal{
    public String color;
    public Dog(String name, int age, String color) {
        //调用父类的,带有两个参数的构造方法,来初始化父类当中的成员
        super(name,age); 
        //在子类成员初始化完成之前要帮父类完成初始化
        this.color = color;
    }
    public void bark(){
        System.out.println(this.name+" 正在汪汪叫....");
    }
}
public class test2 {
    public static void main(String[] args) {
        Dog dog = new Dog("阿黄",2,"白色");
    }
}

注意事项:

  • 1.若父类定义无参或者默认的构造方法,在子类构造方法的第一行默认有隐含的super。
  • 2.在子类构造方法中,super( )调用父类构造时,必须在子类构造函数的第一条语句。
  • 3.super( )只能在子类构造方法中出现一次,并且不能和this( )同时出现。

7.super和this

super和this都可以在成员方法中用来访问:成员方法,成员变量,构造方法。都可以作为构造方法的第一条语句,那他们之间有什么区别呢?

【相同点】

  • 1. 都是Java中的关键字
  • 2. 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
  • 3. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在

【不同点】

  • 1.this是当前对象的引用,super是从父类继承下来的成员引用。
  • 2. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
  • 3. 在构造方法中:this(...)用于调用本类构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造方法中出现
  • 4. 构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有

8.深入了解初始化

我们知道在没有继承关系时执行顺序是: 静态代码块 >  实例代码块  >  构造代码块

那在继承关系上的执行顺序呢?

class Person{
    public String name;
    public int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("父类的构造方法");
    }
    {
        System.out.println("父类的实例");
    }
    static {
        System.out.println("父类的静态方法");
    }
}
class Student extends Person{
    public Student(String name, int age) {
        super(name, age);
        System.out.println("子类的构造方法");
    }
    {
        System.out.println("子类的实例");
    }
    static {
        System.out.println("子类的静态方法");
    }
}
public class test3 {
    public static void main(String[] args) {
        Student student1 = new Student("张三",18);
        System.out.println("==========");
        Student student2 = new Student("李四",19);
    }
}

运行结果:

结论:

1、父类静态代码块优先于子类静态代码块执行,且是最早执行

2、父类实例代码块和父类构造方法紧接着执行

3、子类的实例代码块和子类构造方法紧接着再执行

4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

9.protected关键字

在类和对象章节中,为了实现封装特性,Java中引入了访问限定符,主要限定:类或者类中成员能否在类外或者其他包中被访问。

protected叫做受保护的

1.同一个包同一个类可以访问。

2. 同一个包的不同类可以访问。

3.不同包的子类可以访问(请看下图)。

10.继承方式

Java支持以下几种继承方式

1.单继承,2.多层继承,3.不同类继承同一类

Java中不支持多继承

建议类之间的继承关系层次不要太复杂,一般我们不希望超过三层的继承关系。

11.final关键字

final关键字可以用来修饰变量,成员方法以及类。

1.修饰变量或字段,表示常量(即不能修改)

2. 修饰类:被final修饰的类称为密封类,代表该类不能被继承。

3. 修饰方法:表示该方法不能被重写(后序介绍)

12.继承与组合

和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。

继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物

组合表示对象之间是has-a的关系,比如:汽车

汽车和其轮胎、发动机、方向盘、车载系统等的关系就应该是组合,因为汽车是有这些部件组成的。

组合和继承都可以实现代码复用,应该使用继承还是组合,需要根据应用场景来选择,一般建议:能用组合尽量用、组合

好啦今天的分享就到这里啦,下期分享多态!

目录
相关文章
|
14天前
|
Java 开发工具 Android开发
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
本系列教程笔记详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。若需快速学习Kotlin,建议查看“简洁”系列教程。本期重点介绍了Kotlin与Java的共存方式,包括属性、单例对象、默认参数方法、包方法、扩展方法以及内部类和成员的互操作性。通过这些内容,帮助你在项目中更好地结合使用这两种语言。
29 1
|
16天前
|
Java 开发工具 Android开发
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
26 2
|
14天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
13 3
|
14天前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
27 2
|
14天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
27 2
|
14天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
26 1
|
14天前
|
Java 编译器 Android开发
Kotlin语法笔记(28) -Kotlin 与 Java 混编
本系列教程详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。对于希望快速学习Kotlin的用户,推荐查看“简洁”系列教程。本文档重点介绍了Kotlin与Java混编的技巧,包括代码转换、类调用、ProGuard问题、Android library开发建议以及在Kotlin和Java之间互相调用的方法。
13 1
|
14天前
|
安全 Java 编译器
Kotlin语法笔记(27) -Kotlin 与 Java 共存(二)
本教程详细讲解Kotlin语法,适合希望深入了解Kotlin的开发者。若需快速入门,建议查阅“简洁”系列教程。本文重点探讨Kotlin与Java共存的高级话题,包括属性访问、空安全、泛型处理、同步机制及SAM转换等,助你在项目中逐步引入Kotlin。
14 1
|
16天前
|
Java 编译器 Android开发
Kotlin语法笔记(28) -Kotlin 与 Java 混编
Kotlin语法笔记(28) -Kotlin 与 Java 混编
19 2
|
21天前
|
Java 程序员 编译器
在Java编程中,保留字(如class、int、for等)是具有特定语法意义的预定义词汇,被语言本身占用,不能用作变量名、方法名或类名。
在Java编程中,保留字(如class、int、for等)是具有特定语法意义的预定义词汇,被语言本身占用,不能用作变量名、方法名或类名。本文通过示例详细解析了保留字的定义、作用及与自定义标识符的区别,帮助开发者避免因误用保留字而导致的编译错误,确保代码的正确性和可读性。
41 3