美文网首页
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类进行"初始化"的时机

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