欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于 Java 类加载初始化

程序员文章站 2022-04-19 18:22:17
...
问:简单说说下面程序的运行结果?
        public class Base {
            public static int s;
            private int a;

            static {
                System.out.println("基类静态代码块, s:" + s);
                s = 1;
            }

            {
                System.out.println("基类实例代码块, a:" + a);
                a = 1;
            }

            public Base() {
                System.out.println("基类构造方法, a:" + a);
                a = 2;
            }

            protected void step() {
                System.out.println("base s: " + s + " , a : " + a);
            }

            public void action() {
                System.out.println("start");
                step();
                System.out.println("end");
            }
        }
        public class Child extends Base {
            public static int s;
            private int a;

            static {
                System.out.println("子类静态代码块, s:" + s);
                s = 10;
            }

            {
                System.out.println("子类实例代码块, a:" + a);
                a = 10;
            }

            public Child() {
                System.out.println("子类构造方法,a:" + a);
                a = 20;
            }

            protected void step() {
                System.out.println("child s: " + s + " , a: " + a);
            }
        }
        public static void main (String[]args ){
            System.out.println("------ new Child()");
            Child cc = new Child();
            System.out.println("\n------ cc.action()");
            cc.action();
            Base bb = c;
            System.out.println("\n-------bb.action()");
            bb.action();
            System.out.println("\n ------- bb.s: " + bb.s);
            System.out.println("\n ------- cc.s: " + cc.s);
        }

答:输出结果如下:

------ new Child()
基类静态代码块, s:0
子类静态代码块, s:0 //子类静态代码块比父类构造方法先执行
基类实例代码块, a:0 //实例代码块比构造方法先执行
基类构造方法, a:1
子类实例代码块, a:0
子类构造方法,a:10

//对于变量无论是类变量还是实例变量都是静态绑定访问的。
------ cc.action() 
start
child s: 10 , a: 20
end

//对于变量无论是类变量还是实例变量都是静态绑定访问的。
-------bb.action()
start
child s: 10 , a: 20
end

 ------- bb.s: 1

 ------- cb.s: 10

其实考察的是 Java 类加载与初始化,加载就是在第一次使用类时动态把类加载到内存,加载一个类会看其父类是否已经加载,如果没有则会先加载父类。类加载过程如下:分配内存保存类信息->给类变量赋默认值->加载父类->设置父子关系->执行类初始化代码;而类初始化过程(先执行父类再执行子类,父类执行时子类静态变量是有默认值 0 的)如下:定义静态变量时的赋值语句->静态初始化代码块;这些 OK 以后就进入实例初始化过程:定义实例变量时的赋值语句->实例初始化代码块->构造方法。 所以上面的结果基本就是这个流程,只是寻找要执行的实例方法时是从对象的实际类型信息开始查找的,找不到才会查父类;对于变量无论是类变量还是实例变量都是静态绑定访问的。