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




  • 相关阅读:
    LeetCode 345. Reverse Vowels of a String 题解
    LeetCode 344. Reverse String 题解
    LeetCode 27. Remove Element 题解
    LeetCode 61. Rotate List 题解
    LeetCode 19.Remove Nth Node From End of List 题解
    Android耗电量
    Android 使用adb查看和修改电池信息
    Android AOP AspectJ 插桩
    Flask相关用法
    Monkey日志信息的11种Event percentage
  • 原文地址:https://www.cnblogs.com/yzjT-mac/p/5868669.html
Copyright © 2011-2022 走看看