JavaSE知识分享——继承(下)

接下来博主会持续更新JavaSE、Java数据结构、MySQL、JavaEE、微服务、Redis等等内容的知识点整理。后续我也会精心制作算法解析、项目经验系列内容,内容绝对干货。相信这些文章能够成为我和大家的"葵花宝典",喜欢的话就关注一下吧!敬请期待!

文章目录

上节我们整理了一部分Java继承知识,这节博主继续为大家分享剩下部分内容

代码执行顺序

  1. 肯定先执行静态代码块,在这个过程的顺序是先父类静态代码块再是子类的静态代码块(再次强调:静态代码块是在内存的方法区,是与堆区的对象分离的),且静态代码块仅仅在类加载到JVM这个过程时会被触发一次,它与对象无关,后面无论实例化多少个对象都不会再执行静态代码块了)
  2. 再执行父类的实例代码块然后父类的构造方法
  3. 最后执行子类的实例代码块然后子类的构造方法
  4. 举个例子:
java 复制代码
class X{
    Y y=new Y();//1
    public X(){//2
        System.out.print("X");
    }
}
class Y{
    public Y(){//3
        System.out.print("Y");
    }
}
public class Z extends X{
    Y y=new Y();//4
    public Z(){//5
        System.out.print("Z");
    }
    public static void main(String[] args) {
        new Z();
    }
}

问:程序输出的结果是什么?

当main方法在执行 new Z() 时,由于 Z 继承自 X ,Java会按照以下顺序执行:

  1. 初始化父类X的实例变量(就是执行父类中成员变量相关代码,也会执行实例化代码块):在 X 中,成员变量 Y y = new Y() 首先执行,调用 Y 的构造函数,打印 "Y" 。

  2. 然后执行父类X的构造函数:然后调用 X 的构造函数,打印 "X" 。

  • 之后才能是子类的事
  1. 初始化子类Z的实例变量(执行子类中成员变量相关代码,也会执行实例化代码块):在 Z 中,成员变量 Y y = new Y() 执行,再次调用 Y 的构造函数,打印另一个 "Y" 。

  2. 然后执行子类Z的构造函数:最后调用 Z 的构造函数,打印 "Z" 。

因此,输出是连续的字符串 "YXYZ"

  • 这个顺序是由Java的对象初始化规则决定的:先父类后子类,实例变量初始化优先于构造函数执行,因为我们要知道 new 类名() 这个代码本身就是先在堆区创建成员,然后调用构造方法(由 类名()引起)。

protected 关键字

  • 被protected修饰的成员,与default(不加修饰符)有个相同点,同一个包内的所有类都有权限使用该成员。
  • 另外在不同包的类,若想使用该成员,就必须是该成员的类的子类,也就是父类中protected修饰的成员在不同包子类中可以直接访问

注意:父类中private成员变量虽然在子类中不能直接访问,但是也继承到子类中了。

我们希望类要尽量做到 "封装", 即隐藏内部实现细节, 只暴露出 必要 的信息给类的调用者.

因此我们在使用的时候应该尽可能的使用比较严格的访问权限. 例如如果一个方法能用 private, 就尽量不要用 public.
不要滥用访问权限,不要为了方便、简单就都用public或private修饰,写代码的时候一定要认真思考, 该类提供的字段、方法到底给 "谁" 使用(是类内部自己用, 还是类的调用者使用, 还是子类使用?)

final 关键字

  • Java中不支持多继承(就是一个子类同时直接继承多个父类)。
  • 虽然Java支持多层继承,我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了.

如果想从语法上进行限制继承, 就可以使用 final 关键字:

  1. 修饰变量或字段,表示常量(即不能修改)
  2. 修饰类:表示此类不能被继承
  3. 修饰方法:表示该方法不能被重写

继承与组合

  • 和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段,就是直接将一些类当做像 int 类似去创建变量就行了。

继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物 组合表示对象之间是has-a的关系,比如:轮胎上汽车的一部分:

java 复制代码
// 轮胎类
class Tire{
// ...
}

class Car{
private Tire tire; // 可以复用轮胎中的属性和方法
private Engine engine; // 可以复用发动机中的属性和方法

// ...
}

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

觉得文章对你有帮助的话就点个赞,收藏起来这份免费的资料吧!也欢迎大家在评论区讨论技术、经验

相关推荐
向着光芒的女孩10 小时前
【IDEA】关不了的Proxy Authentication弹框探索过程
java·ide·intellij-idea
Filotimo_11 小时前
Spring Boot 整合 JdbcTemplate(持久层)
java·spring boot·后端
智商低情商凑11 小时前
Go学习之 - Goroutines和channels
开发语言·学习·golang
半桶水专家11 小时前
Go 语言时间处理(time 包)详解
开发语言·后端·golang
编程点滴11 小时前
Go 重试机制终极指南:基于 go-retry 打造可靠容错系统
开发语言·后端·golang
李慕婉学姐11 小时前
【开题答辩过程】以《“饭否”食材搭配指南小程序的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·spring·小程序
实心儿儿11 小时前
C++ —— 模板进阶
开发语言·c++
萧鼎12 小时前
Python PyTesseract OCR :从基础到项目实战
开发语言·python·ocr
abments12 小时前
pgsql timestamp without time zone > character varying解决方案
java
二川bro12 小时前
第57节:Three.js企业级应用架构
开发语言·javascript·架构