• Java类初始化顺序经典实例


    一、阿里巴巴笔试题:

    复制代码
     1 public class T  implements Cloneable {
     2     public static int k = 0;
     3     public static T t1 = new T("t1");
     4     public static T t2 = new T("t2");
     5     public static int i = print("i");
     6     public static int n = 99;
     7 
     8     public int j = print("j");
     9     
    10     {
    11         print("构造块");
    12     }
    13 
    14     static {
    15         print("静态块");
    16     }
    17 
    18     public T(String str) {
    19         System.out.println((++k) + ":" + str + "    i=" + i + "  n=" + n);
    20         ++n;
    21         ++i;
    22     }
    23 
    24     public static int print(String str) {
    25         System.out.println((++k) + ":" + str + "   i=" + i + "   n=" + n);
    26         ++n;
    27         return ++i;
    28     }
    29     
    30     public static void main(String[] args) {
    31         
    32     }
    33 }
    复制代码

    二、加载过程分析:

    执行main时,先加载所在类,声明静态变量,并初始化静态变量执行静态代码块(按顺序执行)

    初始化到t1时,暂停类加载,先实例化,此时k=0,而i,n都未初始化,系统默认值为0
    初始化j时,k自增为1,i,n为0,输出“1:j i=0 n=0”,n,i自增为1
    执行代码块,输出“2:构造块 i=1 n=1”,n,i自增为2
    执行构造函数,输出“3:t1 i=2 n=2”,n,i自增为3

    初始化到t2时,暂停类加载,先实例化,此时k=3,i,n都还未初始化,但已自增为3
    初始化j时,k自增为4,i,n未初始化为3,输出“4:j i=3 n=3”,n,i自增为4
    执行代码块,输出“5:构造块 i=4 n=4”,n,i自增为5
    执行构造函数,输出“6:t2 i=5 n=5”,n,i自增为6

    初始化i,输出“7:i i=6 n=6”,n,i自增为7,返回自增后的i赋值给i
    初始化n,赋值99
    执行静态块,输出“8:静态块 i=7 n=99”,i自增为8,n自增为100

    完成类加载

    三、涉及知识点:
    1.类加载过程:
    加载某类前先加载其父类
    加载某类时,先声明静态成员变量,初始化为默认值,再初始化静态成员变量执行静态代码块
    初始化静态成员变量执行静态代码块时,是按顺序执行(初始化静态成员变量的本质就是静态代码块)

    2.实例化过程:
    对某类实例化前,先对其父类进行实例化
    实例化某类时,先声明成员变量,初始化为默认值,再初始化成员变量执行代码块
    初始化成员变量执行代码块时,是按顺序执行

    3.在某类加载过程中调用了本类实例化过程(如new了本类对象),则会暂停类加载过程先执行实例化过程,执行完毕再回到类加载过程


    4.类的主动使用与被动使用:
    主动使用例子:
    1):最为常用的new一个类的实例对象
    2):直接调用类的静态方法。
    3):操作该类或接口中声明的非编译期常量静态字段
    4):反射调用一个类的方法。
    5):初始化一个类的子类的时候,父类也相当于被程序主动调用了
    (如果调用子类的静态变量是从父类继承过来并没有复写的,那么也就相当于只用到了父类的东东,和子类无关,
    所以这个时候子类不需要进行类初始化)。
    6):直接运行一个main函数入口的类。

    所有的JVM实现,在首次主动使用某类的时候才会加载该类。

    被动使用例子:
    7):子类调用父类的静态变量,子类不会被初始化。只有父类被初始化。对于静态字段,只有直接定义这个字段的类才会被初始化.
    8):通过数组定义来引用类,不会触发类的初始化,如SubClass[] sca = new SubClass[10];
    9):访问类的编译期常量,不会初始化类

    5.编译期常量:
    写到类常量池中的类型是有限的:String和几个基本类型
    String值为null时,也不会写到类常量池中
    使用new String("xx")创建字符串时,得到的字符串不是类常量池中的

    6.对于通过new产生一个字符串(假设为 ”china” )时,会先去常量池中查找是否已经有了 ”china” 对象,
    如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此 ”china” 对象的拷贝对象。

    7.类成员变量才会有默认的初始值
    byte:0(8位)
    short:0(16位)
    int:0(32位)
    long:0L(64位)
    char:u0000(16位),代表NULL
    float:0.0F(32位)
    double:0.0(64位)
    boolean: flase

    8.局部变量声明以后,Java 虚拟机不会自动的为它初始化为默认值。
    因此对于局部变量,必须先经过显示的初始化,才能使用它。
    如果编译器确认一个局部变量在使用之前可能没有被初始化,编译器将报错。

    9.数组和String字符串都不是基本数据类型,它们被当作类来处理,是引用数据类型。
    引用数据类型的默认初始值都是null

  • 相关阅读:
    SQL注入(转载)
    htmlTable To jpeg
    oracle 中文乱码 全变成 '靠'
    oracle 跨库查询
    oracle 备份还原数据库
    jquery 非异步读取数据
    oracle 游标 简单使用
    自增列的一种方法收藏
    oracle 导出txt 数据,excel 数据
    oracle 简单job
  • 原文地址:https://www.cnblogs.com/CodingAndRiding/p/7599805.html
Copyright © 2020-2023  润新知