【Java SE】继承的详解(下)

简介: 继承(inheritance)机制:这个机制是面向对象程序设计中一个可以使代码复用的重要手段,他可以在原有类的特性上进行扩展,增加新的功能,由继承下来的类,称为派生类,从而实现代码复用

3、再谈代码块

3.1 回顾

上期我们测试过代码块,发现执行顺序的优先级分别是 静态代码块 -> 实例代码块 -> 构造方法 分别是这种执行循序。

  • 静态代码块最先执行,并且只执行一次,因为是再JVM加载类的时候就开辟了。
  • 当有对象创建时就会执行实例代码块,实例代码块执行完毕后,接着执行构造方法

3.2 继承关系中的执行顺序

如果父类中有静态代码块,实例代码块,构造方法,而子类中也有这些,那么他们的先后执行顺序是什么呢?我们用代码来做测试:

public class Person {
    public String name;
    public String sex;
    public int age;
    {
        System.out.println("执行 Person 实例代码块!");
    }
    static {
        System.out.println("执行 Person 静态代码块!");
    }
    public Person() {
        System.out.println("执行 Person 构造方法!");
    }
}
class Student extends Person {
    public float score;
    {
        System.out.println("执行 Student 实例代码块!");
    }
    static {
        System.out.println("执行 Student 静态代码块!");
    }
    public Student() {
        System.out.println("执行 Student 构造方法!");
    }
}
class Test {
    public static void main(String[] args) {
        Student student = new Student();
    }
}

通过测试,我们可以得出以下结论:

  • 静态代码块永远是最早执行,但是父类优于子类
  • 紧接着就是父类实例代码块和构造方法,再就是子类实例代码块和构造方法
  • 第二次实例化的时候,父类和子类静态代码块将不会执行(可以自己下去测试,上一期也测试)

4、 protected 关键字

4.1 protected关键字的作用

其实在上一期中我们就已经简单的介绍了以下这个关键字,只是当时我们并不知道继承的概念,所以当时出现,允许在不同包中的子类中访问这个权限,相信大家目前应该已经了解他的权限了,那这里我们就做一个小的代码演示:

看到这,相信你就理解了 protected 关键字了,建议大家自己下来多尝试敲代码,多测试,简单来说,要想在不同的包中访问 protected 修饰的成员,首先你这个类必须称为那个类的子类。

4.2 子类如何访问父类 private 修饰的成员?

其实本期的所有代码,除了4.1例子之外,不管是父类还是子类的成员变量都是 public 修饰的, 那我们前面学过 private 修饰的成员只能在本类中访问,也就是说如果父类中有 private 修饰的成员,我们也会继承下来,但是无法直接访问,因为权限限定符,他限定的就是你访问的权限,那我们就想访问父类使用 private 修饰的成员怎么办?有一个目前能理解的方法:在父类中写一个公共的获取方法就行,比如 public String getName() { return name; }  

4.3 为什么 private 和 protected 不能修饰外部类?

我们要先了解他们的权限:

private:如果使用 private 修饰了外部类,那么这个类将不能在其他类中进行实例化,也就是不能用这个类来创建对象,那么这个类的属性和方法就不能被访问,这个类将毫无意义,所Java直接不允许使用 private 修饰外部类

protected:如果 A 类用了 protected 修饰,那么在不同包中的 B 类要想访问 A 类的话,B 必须为 A 的子类, 但是 B 想继承 A 的前提是 B 可以访问到 A,这里就会发生冲突,继承是为了拥有父类的属性和方法,所以 protected 是用来修饰类的成员的

总结:

也就是说,如果我这个类的属性和方法可以被任何的子类访问,我就用 protected,如果我这个类的属性和方法只能在本类中访问,我就用 private,如果我们不想让这个类被继承,就用 final(后续讲)

5、Java中的继承方式

Java中支持一个类单继承,也就是一个类继承另一个类

Java中支持多层继承,也就是一个类继承了另一个类,另一个类又继承了另一个类

Java中支持不同类继承同一个类,就是一个父类有多个子类,但子类只有一个父类

Java中不支持多继承,也就是不能一个子类有多个父类!

一般我们不希望出现超过三层的继承关系,继承层次太多,就可能考虑要对代码重构了!

6、final 关键字

这个关键字在前面我们也见过,final简单来说可以修饰变量,成员方法,类,我们下面就来看看修饰他们所不同的表现:

final修饰变量:这个我们在之前说过,修饰了变量或者字段,表示常量,是不能被修改的

final修饰方法:表示方法不能被重写(下期介绍)

final修饰类:表示该类不能被继承:

7、继承与组合

组合就相当于一个东西是由什么零件组装而成的,而继承则是把相同的部分抽取了出来,两个其实都是实现代码复用的效果

  • 继承与对象之间的关系是:is - a:比如猫是动物,狗也是动物,他们都属于动物
  • 组合于对象之间的关系是:has - a:比如主机是由CPU,主板,显卡等组合而成形成主机

这个在我们后续的学习中也会接触,这里先做一个简单了了解即可

相关文章
|
3月前
|
Java 程序员
Java中的继承和多态:理解面向对象编程的核心概念
【8月更文挑战第22天】在Java的世界中,继承和多态不仅仅是编程技巧,它们是构建可维护、可扩展软件架构的基石。通过本文,我们将深入探讨这两个概念,并揭示它们如何共同作用于面向对象编程(OOP)的实践之中。你将了解继承如何简化代码重用,以及多态如何为程序提供灵活性和扩展性。让我们启程,探索Java语言中这些强大特性的秘密。
|
15天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
13 3
|
15天前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
27 2
|
15天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
27 2
|
15天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
26 1
|
2月前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
26天前
|
Java 测试技术 编译器
Java零基础-继承详解!
【10月更文挑战第4天】Java零基础教学篇,手把手实践教学!
29 2
|
1月前
|
Java 编译器
在Java中,关于final、static关键字与方法的重写和继承【易错点】
在Java中,关于final、static关键字与方法的重写和继承【易错点】
20 5
|
1月前
|
Java
java继承和多态详解
java继承和多态详解
39 5
|
1月前
|
Java 编译器
【一步一步了解Java系列】:子类继承以及代码块的初始化
【一步一步了解Java系列】:子类继承以及代码块的初始化
20 3