zoukankan      html  css  js  c++  java
  • 深入理解类加载机制

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

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

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

    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




  • 相关阅读:
    drf规范——请求与响应
    序列化器——Serializer
    drf 安装与配置
    CBV源码——View,APIView
    django restful framework —— Drf 规范一
    Vue——五
    Vue——四
    今日复习
    冒泡排序
    考试总结
  • 原文地址:https://www.cnblogs.com/yzjT-mac/p/5868669.html
Copyright © 2011-2022 走看看