对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 调用执行。

不知你们有没有好奇类加载起是如何定位到具体到类并读取的呢?

类加载器结构

要了解这个问题的答案,我们就需要了解类加载器的结构。

java 重写boolean java 重写jar包类 双亲委派_Java双亲委派模型


类加载器类似于原始部落结构,存在权利等级制度。

  • 最高一层是家族中威望最高的BootStrap ClassLoader,它是在JVM启动时创建的,通常由与操作系统相关的本地代码实现,是最根基的类加载器。负责装载最核心的Java类,加载位于jre/lib/*.jar的字节码,最先被加载,比如ObjectSytem,String
  • 第二层是在JDK9版本中,成为Platform ClassLoader, 即平台类加载器,用以加载一些扩展的系统类,比如XML,加密,压缩相关的功能类等。JDK9 之前是Extendsion 类加载器,加载位于jre/lib/etc/*.jar的字节码,第二被加载
  • 第三层是Application ClassLoader 是我们自己应用程序的类加载器,用以加载用户自定义的CLASSPATH 路径下的类。

值得注意的是,类加载器具有等级制度,但是并非继承关系,以组合的方式来复用父加载器的功能。

何为双亲委派模型?

java 重写boolean java 重写jar包类 双亲委派_Java双亲委派模型_02

低层次的当前类加载器,不能覆盖更高层次类加载器已加载的类。如果低层次的类加载器想加载一个未知类,要非常礼貌地向上级逐级询问:“请问,这个类已经加载了么?”
被询问的高层次类加载器会自问两个问题:

  • 第一:我是否已加载过此类?
  • 第二:如果没有,我是否可以加载此类?

只有当所有高层次类加载器在两个问题上的答案均为否 时,才可以当当前类加载这个未知类。
如上图所示,左侧绿色箭头向上逐级询问是否已加载此类,直致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 中对重载,重写,继承的理解示例如下:

当子类调用开轿车方法的时候:

java 重写boolean java 重写jar包类 双亲委派_重写_03


当父类调用开轿车方法的时候:

java 重写boolean java 重写jar包类 双亲委派_Java双亲委派模型_04


本篇完~