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; // 可以复用发动机中的属性和方法

// ...
}

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

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

相关推荐
期待のcode1 小时前
MyBatisX插件
java·数据库·后端·mybatis·springboot
醇氧4 小时前
【Windows】优雅启动:解析一个 Java 服务的后台启动脚本
java·开发语言·windows
sunxunyong4 小时前
doris运维命令
java·运维·数据库
菜鸟起航ing4 小时前
Spring AI 全方位指南:从基础入门到高级实战
java·人工智能·spring
古城小栈4 小时前
Docker 多阶段构建:Go_Java 镜像瘦身运动
java·docker·golang
MapGIS技术支持4 小时前
MapGIS Objects Java计算一个三维点到平面的距离
java·开发语言·平面·制图·mapgis
Coder_Boy_4 小时前
业务导向型技术日志首日记录(业务中使用的技术栈)
java·驱动开发·微服务
程序员zgh5 小时前
C++ 互斥锁、读写锁、原子操作、条件变量
c语言·开发语言·jvm·c++
小灰灰搞电子5 小时前
Qt 重写QRadioButton实现动态radioButton源码分享
开发语言·qt·命令模式
by__csdn5 小时前
Vue3 setup()函数终极攻略:从入门到精通
开发语言·前端·javascript·vue.js·性能优化·typescript·ecmascript