Java类初始化时机测试方法解析

<clinit>()方法

Java 类加载的初始化过程中,编译器按语句在源文件中出现的顺序,依次自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并产生方法。 如果类中没有静态语句和静态代码块,那可以不生成<clinit>() 方法。

并且 <clinit>() 不需要显式调用父类(接口除外,接口不需要调用父接口的初始化方法,只有使用到父接口中的静态变量时才需要调用)的初始化方法 <clinit>(),虚拟机会保证在子类的 <clinit>() 方法执行之前,父类的 <clinit>() 方法已经执行完毕(所以java.lang.Object 类总是第一个被加载)

准备父类和子类

class Father {

  static int father_a = 1;

  static {
    System.out.println("父类静态代码块执行");
  }

  static class StaticInnerClass {
    static {
      System.out.println("静态内部类静态代码块执行");
    }
  }
}

class Son extends Father {

  static {
    System.out.println("子类静态代码块执行");
    son_a = 300;
  }

  static int son_a = 100;
  static final int M = 1;
}

Main方法:

1:父类没有被引用但是会被先加载

new Son();

2:反射也会产生主动引用:

Class a = Class.forName("clinit.Son");

(运行结果同1)

3:子类使用父类静态变量或方法不会产生类的引用

System.out.println("Father.a = " + Son.father_a);

4:通过类创建数组不会加载类(只是开辟一块空间)

Son[] sons = new Son[8];

5:使用常量不会加载父类和之类(常量在Linking阶段就保存在常量池当中了)

System.out.println("Son.CONST = " + Son.CONST);

6:引用静态内部类不会加载外部类(应用于单例模式)

new Father.StaticInnerClass();

代码总结:

public static void main(String[] args) throws Exception {

//    1.父类没有被引用但是会被先加载
//    new Son();
//    2.反射会产生主动引用
//    Class a = Class.forName("clinit.Son");
//    3.子类使用父类静态变量或方法不会产生类的引用
//    System.out.println("Father.a = " + Son.father_a);
//    4.通过类创建数组不会加载类(只是开辟一块空间)
//    Son[] sons = new Son[8];
//    5.使用常量不会加载父类和之类(常量在Linking阶段就保存在常量池当中了)
//    System.out.println("Son.CONST = " + Son.CONST);
//    6.引用静态内部类不会加载外部类(应用于单例模式)
//    new Son.StaticInnerClass();
  }
}

PS:由于是按出现的顺序执行的,为了避免不必要的麻烦,应尽量把静态变量写在静态代码块之前

public class Test {
  public static void main(String[] args) {
    System.out.println("a = " + cls.a);
  }
}
class cls {
  static int a = 10;8   static { a = 20; }9 }

如果 调换顺序输出结果将是 a = 10

 class cls {
   static { a = 20; }
   static int a = 10;
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java父类和子类初始化顺序的深入理解

    继承类的构建过程是向外扩散的,子类初始化了,父类一定也初始化了 复制代码 代码如下: class Art{ Art(){  System.out.println("Art"); }}class Drawing extends Art{ Drawing(){  System.out.println("Drawing"); }}public class Cartoon extends Drawing { Cartoon(){  System.out.println(&q

  • Java类的加载连接和初始化实例分析

    本文实例讲述了Java类的加载连接和初始化.分享给大家供大家参考,具体如下: 一 点睛 1 类加载 当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过加载.连接.初始化三个步骤来对该类进行初始化,如果没有意外,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载或类初始化. 类加载指的是将类的class文件读入内存,并为之创建一个java.lang.Class对象,也就是说当程序使用任何类时,系统都会为之建立一个java.lang.Class对象. 2 类数据的来源 通过

  • Java类加载初始化的过程及顺序

    Java类的加载说明 Java类的编译代码都存在于它自己的独立文件中(class),该文件只在需要使用程序代码时才会被加载. 类加载在创建类的第一个对象时发生,但当访问static域或static方法时,也会发生加载. 构造器也是static方法,尽管static关键字没有显式写出,故可进一步说,类是在任何static成员被访问时加载的. 示例说明加载过程 示例源于<Java编程思想> //父类 public class SuperClass { protected int super_a;

  • Java类继承关系中的初始化顺序实例详解

    本文实例讲述了Java类继承关系中的初始化顺序.分享给大家供大家参考,具体如下: Java类初始化的顺序经常让人犯迷糊,现在本文尝试着从JVM的角度,对Java非继承和继承关系中类的初始化顺序进行试验,尝试给出JVM角度的解释. 非继承关系中的初始化顺序 对于非继承关系,主类InitialOrderWithoutExtend中包含了静态成员变量(类变量)SampleClass 类的一个实例,普通成员变量SampleClass 类的2个实例(在程序中的顺序不一样)以及一个静态代码块,其中静态代码块

  • java类中元素初始化顺序详解

    复制代码 代码如下: public class Test4 {    @Test    public void test(){        child child = new child();    }} class parent{    public static String parentStaticField = "父类静态变量";    public String parentNormalField ="父类普通变量";    static {      

  • Java类变量和成员变量初始化过程的应用介绍

    一.类的初始化 对于类的初始化:类的初始化一般只初始化一次,类的初始化主要是初始化静态成员变量. 类的编译决定了类的初始化过程. 编译器生成的class文件主要对定义在源文件中的类进行了如下的更改: 1)       先按照静态成员变量的定义顺序在类内部声明成员变量. 2)       再按照原java类中对成员变量的初始化顺序进行初始化. 一个java类和编译后的class对应的转换如下: 源文件: 复制代码 代码如下: public class Person{ public static S

  • Java类初始化和实例化中的2个“雷区”

    在考虑类初始化时,我们都知道进行子类初始化时,如果父类没有初始化要先初始化子类.然而事情并没有一句话这么简单. 首先看看Java中初始化触发的条件: (1)在使用new实例化对象,访问静态数据和方法时,也就是遇到指令:new,getstatic/putstatic和invokestatic时: (2)使用反射对类进行调用时: (3)当初始化一个类时,父类如果没有进行初始化,先触发父类的初始化: (4)执行入口main方法所在的类: (5)JDK1.7动态语言支持中方法句柄所在的类,如果没有初始化

  • 在java中 利用匿名内部类进行较简洁的双括弧初始化的方法

    java的collection集合框架如set.map.list没有提供任何简便的方法供初始化.而每次建立集合都要将值一个个add进去.如 复制代码 代码如下: Set<Character> letter=new HashSet<Character>();letter.add('a');letter.add('b');//... 非常繁琐. 但用匿名内部类的话.可以略为简便些. 复制代码 代码如下: Set<Character> letter=new HashSet&l

  • Java类初始化时机测试方法解析

    <clinit>()方法 Java 类加载的初始化过程中,编译器按语句在源文件中出现的顺序,依次自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并产生方法. 如果类中没有静态语句和静态代码块,那可以不生成<clinit>() 方法. 并且 <clinit>() 不需要显式调用父类(接口除外,接口不需要调用父接口的初始化方法,只有使用到父接口中的静态变量时才需要调用)的初始化方法 <clinit>(),虚拟机会保证在子类的 <clinit>

  • Java类初始化执行流程解析

    测试代码: package com.test.ClassLaoderTest; public class test1 { public static String s_variable = "静态变量"; public String init_variable = "公开的变量"; private String p_variable = "私有的变量"; //静态代码块 static { System.out.println(s_variable

  • Java字段初始化的规律解析

    这篇文章主要介绍了Java字段初始化的规律解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在Java中定义一个类后,有三种方式可以对其中的变量进行初始化:直接输入,初始化块,构造函数. 而对于这三者的优先级,其应该是: 1.类的构造函数(构造方法): 当创建一个对象时,其构造函数就会自动调用.构造方法必须与类名相同,无返回值. 如果程序员没有定义一个构造函数时,系统会自动定义一个不含参数的"默认构造函数",在自定义构造函数后就不再

  • 通过实例解析Java类初始化和实例初始化

    一.背景: 存在类Father和类Son,其中类Son继承了Father类. 1.父类Father代码 2.子类Son代码 *初始化包括? 成员变量赋初值.代码块.构造器 注意方法是被调用的,有人调用它它才执行相应的东西. 二.类初始化 在一开始,注释掉main方法中的代码,执行结果如下. 类初始化: 1.创建实例需要先加载并初始化该类 此处main方法所在的类需要先加载并初始化 2.子类初始化要先初始化其父类 3.类初始化即是执行clinit(ClassInit)方法 A.(静态!)分为 静态

  • 详解Java 类的加载、连接和初始化

    系统可能在第一次使用某个类时加载该类,也可能采用预加载机制来加载某个类.本节将会详细介绍类加载.连接和初始化过程中的每个细节. JVM 和类 当调用 java 命令运行某个 Java 程序时,该命令将会启动一个 Java 虚拟机进程,不管该 Java 程序有多么复杂,该程序启动了多少个线程,它们都处于该 Java 虚拟机进程里.正如前面介绍的,同一个 JVM 的所有线程.所有变量都处于同一个进程里,它们都使用该 JVM 进程的内存区.当系统出现以下几种情况时,JVM 进程将被终止. 程序运行到最

  • Java类的加载时机与过程

    目录 1 开门见山 2 类的加载时机 3 何时开始类的初始化 4 被动引用例子 5 类的加载过程 5.1 加载 5.2验证 5.3准备 5.4 解析 5.5 初始化 1 开门见山 以前曾经看到过一个java的面试题,当时觉得此题很简单,可是自己把代码运行起来,可是结果并不是自己想象的那样.题目如下: class SingleTon { private static SingleTon singleTon = new SingleTon(); public static int count1; p

  • 简单了解java类的初始化以及类的实例化

    前言 上一篇我们知道了一个类的生命周期是:加载->验证->准备->解析->初始化->使用->卸载. 当初始化完成以后,一个类所有的类变量(被static修饰的变量)都被赋值.但是未被static修饰的成员变量又是何时被赋值的呢? 一个类何时会被初始化 一个类何时被初始化可以分为以下几类: 1.创建类的实例(new). 2.访问某个类或接口的静态变量,或者对该静态变量赋值. 3.调用类的静态方法. 4.通过反射方式执行以上三种行为. 5.初始化子类的时候,会触发父类的初始

随机推荐