对Java 中双亲委派模型和重载,重写,继承的理解
- 1.1 前言
- 1.1.1 知识点
- 1.1.1.1 双亲委派模型
- 类加载器结构
- 何为双亲委派模型?
- 什么时候需要自定义类加载器?
- 1.1.1.2 重写
- 1.1.1.3 重载
- 1.1.1.4 继承
- 1.1.2 Java 中对重载,重写,继承的理解示例
1.1 前言
这篇博文来分享下博主对Java 中对双亲委派模型和重载,重写,继承的理解。
1.1.1 知识点
1.1.1.1 双亲委派模型
在Java中,万事万物皆为对象,不同的对象就是不同的类。
众所周知,一个
*.java
文件要经过javac编译器编译成*.class
,然后经过类加载器将*.class
加载到JVM
虚拟机中的不同内存区域,等待CPU 调用执行。
不知你们有没有好奇类加载起是如何定位到具体到类并读取的呢?
类加载器结构
要了解这个问题的答案,我们就需要了解类加载器的结构。
类加载器类似于原始部落结构,存在权利等级制度。
- 最高一层是家族中威望最高的BootStrap ClassLoader,它是在JVM启动时创建的,通常由与操作系统相关的本地代码实现,是最根基的类加载器。负责装载最核心的Java类,加载位于jre/lib/*.jar的字节码,最先被加载,比如
Object
,Sytem
,String
等- 第二层是在JDK9版本中,成为Platform ClassLoader, 即平台类加载器,用以加载一些扩展的系统类,比如XML,加密,压缩相关的功能类等。JDK9 之前是Extendsion 类加载器,加载位于jre/lib/etc/*.jar的字节码,第二被加载
- 第三层是Application ClassLoader 是我们自己应用程序的类加载器,用以加载用户自定义的CLASSPATH 路径下的类。
值得注意的是,类加载器具有等级制度,但是并非继承关系,以组合的方式来复用父加载器的功能。
何为双亲委派模型?
低层次的当前类加载器,不能覆盖更高层次类加载器已加载的类。如果低层次的类加载器想加载一个未知类,要非常礼貌地向上级逐级询问:“请问,这个类已经加载了么?”
被询问的高层次类加载器会自问两个问题:
- 第一:我是否已加载过此类?
- 第二:如果没有,我是否可以加载此类?
只有当所有高层次类加载器在两个问题上的答案均为否 时,才可以当当前类加载这个未知类。
如上图所示,左侧绿色箭头向上逐级询问是否已加载此类,直致BootStrap ClassLoader,然后向下逐级询问是否可以加载此类,如果都加载不了,则通知发起加载请求的当前类加载器,准予加载。
什么时候需要自定义类加载器?
- 隔离加载类
在某些框架内进行中间件与应用的模块隔离,把类加载到不同的环境。比如,阿里内某容器框架通过自定义类加载器确保应用中依赖的jar包不会影响到中间件运行时使用的jar包。
- 修改类加载方式
类的加载模型并非强制,除BootStrap之外,其他的类加载器并非一定要引入,或者根据实际情况在某个时间点进行按需进行动态加载。
- 扩展加载源
比如从数据库,网络,甚至是电视机顶盒进行加载。- 防止源码泄漏
Java代码容易被编译和篡改,可以进行编译加密,那么类加载器也需要自定义,还原加密的字节码。
1.1.1.2 重写
同时需要注意的是,当子类的方法和父类的方法名称,参数,返回值等都一样的时候,触发方法重写,
即子类的方法会覆盖重写了父类的方法。
class Father{
protected Boolean haveHouseInCity=true;
public void haveGoods(String house){
System.out.println("在农村有房子"+house);
}
}
class Son extends Father{
protected Boolean haveCarInCity=true;
public void haveGoods(String house){
System.out.println("在市里有房子"+house);
}
}
1.1.1.3 重载
当类的方法名称一样,但是参数列表不一样的时候触发重载
即:子类增加了一个和父类中方法同名,但是参数个数或类型不同的方法。
class Father{
protected Boolean haveHouseInCity=true;
public void haveGoods(String house){
System.out.println("在市里有房子"+house);
}
}
class Son extends Father{
protected Boolean haveCarInCity=true;
public void haveGoods(String car,String house){
System.out.println("在市里有房子"+house+"也有车"+car);
}
}
1.1.1.4 继承
在java中,不同的对象用类表示,类与类之间存在继承关系,即如果子类中没有的方法,可以从父类中继承。
如下示例中,Son对象在市里没有房子,但是它的父类有,那么输出结果 Son 在市里也有房子。
/**
* @author qing-feng.zhao
*/
public class Test {
public static void main(String[] args) {
Son son=new Son();
System.out.println("son有没有房子?"+(son.haveHouseInCity==true?"有":"没有"));
}
static class Father{
protected Boolean haveHouseInCity=true;
}
static class Son extends Father{
protected Boolean haveCarInCity=true;
}
}
输出结果:
son在市里有没有房子?有
值得注意的是,子类可以通过继承拥有父类public 或protected 的属性和方法,但父类没有办法拥有子类的属性或方法。
在这个例子中就是: Son可以拥有Father在市里的房子,但是Father对象无法调用Son 的在市里的车。
1.1.2 Java 中对重载,重写,继承的理解示例
Java 中对重载,重写,继承的理解示例如下:
当子类调用开轿车方法的时候:
当父类调用开轿车方法的时候:
本篇完~