• 深入理解类加载机制


    之前的博客说了,类加载分为五个阶段

    加载->链接(验证+准备+解析)->初始化(使用前的准备)->使用->卸载

    今天,遇到一个很有趣的现象:

    public class Dervied extends Base {
    
        private  String name = "dervied";
    
        public Dervied() {
            tellName();
            printName();
        }
        
        public void tellName() {
            System.out.println("Dervied tell name: " + name);
        }
        
        public void printName() {
            System.out.println("Dervied print name: " + name);
        }
    
        public static void main(String[] args){
            
            new Dervied();    
        }
    }


    class Base {

    private String name = "base";

    
    

    public Base() {
    tellName();
    printName();
    }

    public void tellName() {
    System.out.println("Base tell name: " + name);
    }

    public void printName() {
    System.out.println("Base print name: " + name);
    }
    }

    
    
    
     

    猜猜输出的结果是什么,或许你会说

    Dervied tell name: base
    Dervied print name: base
    Dervied tell name: dervied
    Dervied print name: dervied

    一开始我也是这么觉得的,但是,实际上输出的结果却是

    Dervied tell name: null
    Dervied print name: null
    Dervied tell name: dervied
    Dervied print name: dervied

    为什么会是Null?,是不是很奇怪,下面我会详细分析

    结合着 加载->链接(验证+准备+解析)->初始化(使用前的准备)->使用->卸载 这几个阶段,我们先来看看。

    首先,new一个Dervied是调用他的构造方法,

      public Dervied() {
            tellName();
            printName();
        }
    我们知道,创建一个子类的实例时,首先会调用其父类无参的构造方法,而调用无参的构造方法之前,会调用父类属性,即调用
    private String name = "base";
    然后
    public Base() {
    tellName();
    printName();
    }


    而tellName();这句会输出
    System.out.println("Base tell name: " + name);
    你可能会想,此时不是已经读取了name吗,为什么最后显示的是Null呢,实际上,虽然此时父类的name是base,但是子类的name还是null,此刻调用的name不是父类的name,而是子类的name,即使写在父类里面。
    所以输出的结果是上面我们看到的那样。
    我们可以对上面的例子做一点改变:
    private  String name = "dervied";改成
    private  static String name = "dervied";
    这样,就可以访问到子类的name了。
    原因是static修饰的变量在类加载的时候就已经被载入了,而我们上面讨论的都是发生在类初始化的时候进行的,所以输出的结果是
     

    Dervied tell name: dervied
    Dervied print name: dervied
    Dervied tell name: dervied
    Dervied print name: dervied




  • 相关阅读:
    [转] Vue + Webpack 组件式开发(练习环境)
    [转] 从零构建 vue2 + vue-router + vuex 开发环境到入门,实现基本的登录退出功能
    [转] Redux入门教程(快速上手)
    [转] 前端数据驱动的价值
    [转] React风格的企业前端技术
    [转] 对Array.prototype.slice.call()方法的理解
    [转] webpack之plugin内部运行机制
    [转] 静态资源的分布对网站加载速度的影响/浏览器对同一域名下并发加载资源数量
    Mysql 版本号、存储引擎、索引查询
    linux 查看CPU、内存、磁盘信息命令
  • 原文地址:https://www.cnblogs.com/yzjT-mac/p/5868669.html
Copyright © 2020-2023  润新知