美文网首页
Java类进行"初始化"的时机

Java类进行"初始化"的时机

作者: SherlockMoon | 来源:发表于2017-09-23 17:23 被阅读0次

类进行"初始化"的必须情况(有且仅有五种情况)

1.遇到new,getstatic,putstatic或invokestatic这4条字节码指令时.
分别对应常见的4种场景,new关键字实例化对象,读取或设置类的静态字段(不包括被final修饰的字段,已在编译期把结果放入常量池中),调用类静态方法时。

public class Main {
    public static void main(String[] args) {
    }
    static class Test{
        static {
            System.out.println("Init Test");
        }
        static int x = 3;
        final static int y = 4;
        static void print() {
            System.out.println("has inited?");
        }
}

在main函数中分别置于以下语句,观察是否执行static代码段。

new Test(); //触发初始化
System.out.println(Test.x);  //触发初始化
Test.x = 4;  //触发初始化
Test.print();  //触发初始化
System.out.println(Test.y);  //不触发初始化
  1. 利用反射对类进行调用时。

在main函数中置于下面语句时,观察是否执行static代码段。

       try { 
            Test.class.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        for (Field field : Test.class.getDeclaredFields()) {
            if (field.getName().equals("x")) {
                try {
                    System.out.println(field.get(Test.class));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
       for (Field field : Test.class.getDeclaredFields()) {
            if (field.getName().equals("y")) {
                try {
                    System.out.println(field.get(Test.class));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

不管是实例化,还是访问static变量,或者是访问static final变量,都会触发初始化。但仅仅是访问field时,置于以下语句时,不会触发初始化。

for (Field field : Test.class.getDeclaredFields()){
    System.out.println(field.getName());
}
  1. 初始化一个类时,若父类未初始化,则先初始化父类.
public class Main {

    public static void main(String[] args) {
        
    }

    static class Fa {
        static {
            System.out.println("Init Fa");
        }
        static int fax = 3;
        static final int fay = 4;
    }

    static class Test extends Fa{
        static {
            System.out.println("Init Test");
        }
        static int x = 3;
        final static int y = 4;
        static void print() {
            System.out.println("has inited?");
        }
    }
}

在main函数置于以下语句

System.out.println(Test.x); //初始化父类,然后初始化子类
System.out.println(Test.fax); //初始化父类,不初始化子类
System.out.println(Test.fay); //不初始化父类,也不初始化子类
  1. 虚拟机启动时,主类(包含main方法的那个类),先初始化此类。
public class Main {
    static {
        System.out.println("Init Main");
    }
    public static void main(String[] args) {
        try {
            Test.class.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    static class Fa {
        static {
            System.out.println("Init Fa");
        }
        static int fax = 3;
        static final int fay = 4;
    }

    static class Test extends Fa{
        static {
            System.out.println("Init Test");
        }
        static int x = 3;
        final static int y = 4;
        static void print() {
            System.out.println("has inited?");
        }
    }
}
/*
打印结果:
Init Main
Init Fa
Init Test
*/

  1. jdk1.7 通过方法句柄的方式动态执行方法或者修改访问static变量时。
public class Main {
    static {
        System.out.println("Init Main");
    }
    public static void main(String[] args) {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        try {
            MethodHandle methodHandle = lookup.findStatic(Test.class, "print", MethodType.methodType(void.class));
            methodHandle.invoke();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

    }

    static class Fa {
        static {
            System.out.println("Init Fa");
        }
        static int fax = 3;
        static final int fay = 4;
    }

    static class Test extends Fa{
        static {
            System.out.println("Init Test");
        }
        static int x = 3;
        final static int y = 4;
        static void print() {
            System.out.println("has inited?");
        }
    }
}

相关文章

  • Java类进行"初始化"的时机

    类进行"初始化"的必须情况(有且仅有五种情况) 1.遇到new,getstatic,putstatic或invok...

  • 我的秋招之路-面经篇

    Java基础 类加载的时机和类初始化的时机(引出tomcat类加载器)JVM和绝大多数用户自定义的类在JVM启动的...

  • 类加载机制

    目录 概念 加载过程 初始化时机 类初始化顺序注意点 双亲委派模型 自定义类加载器 类加载 概念 Java虚拟机把...

  • Java类的初始化时机

    一个Java对象的创建过程往往包括 类初始化 和 类实例化 两个阶段。本文讨论的是『类初始化』的时机,以及利用这一...

  • 类加载的时机

    目录 1、类加载的生命周期2、类初始化阶段进行的时机(主动引用)3、被动引用(不会触发类初始化)4、接口的加载过程...

  • java类变量的初始化时机

    答案:-2.8 17.2分析:考查类变量的初始化时机。从内存角度分析此程序。第一步:类加载时,为static类成...

  • Java类初始化的时机详解

    1. 概述 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(V...

  • 类加载

    类加载时机 虚拟机规范中没有规定类加载的时机,但是规定了需要进行初始化的5种情况(而加载、验证、准备必须在此之前)...

  • java构造器初始化与清理

    java构造器初始化先后顺序: 若此类继承于某基类,则先初始化基类,以此类推,找到最基本的父类,先对基类进行初始化...

  • Java 中的 static 使用之静态初始化块

    Java 中的 static 使用之静态初始化块 Java 中可以通过初始化块进行数据赋值。如: 在类的声明中,可...

网友评论

      本文标题:Java类进行"初始化"的时机

      本文链接:https://www.haomeiwen.com/subject/qxgcextx.html