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

// ...
}

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

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

相关推荐
Catfood_Eason3 小时前
CMPP3020作业2
java·开发语言
CryptoRzz3 小时前
印度实时股票数据源接口对接文档-IPO新股、k线数据
java·开发语言·数据库·区块链
宸津-代码粉碎机3 小时前
Java内部类内存泄露深度解析:原理、场景与根治方案(附GC引用链分析)
java·开发语言·jvm·人工智能·python
NEU-UUN3 小时前
C语言 . 第三章第二节 .递归函数
c语言·开发语言
weixin_307779133 小时前
Python编码规范之字符串规范修复程序详解
开发语言·python·代码规范
郝学胜-神的一滴4 小时前
深入理解 Python 的 __init_subclass__ 方法:自定义类行为的新方式 (Effective Python 第48条)
开发语言·python·程序人生·个人开发
東雪木4 小时前
Java基础语言进阶学习——1,JVM内存模型(堆、栈、方法区)
java·jvm·学习
毕设源码-郭学长4 小时前
【开题答辩全过程】以 常二社区线上养老院管理系统为例,包含答辩的问题和答案
java·eclipse
初见无风4 小时前
3.0 Lua代码中的闭包
开发语言·lua·lua5.4