类加载及初始化顺序例题

目录

1、JAVA的类加载期负责整个生命周期内的class的初始化和加载工作,就虚拟机的规范来说,以下代码会输出什么结果?

2、JAVA的类加载期负责整个生命周期内的class的初始化和加载工作,就虚拟机的规范来说,以下代码会输出什么结果?

3、这个同2

4、继承是JAVA语言的一个特性,针对类的继承,虚拟机会如何进行父类和子类的初始化加载呢?

5、继承是JAVA语言的一个特性,针对类的继承,虚拟机会如何进行父类和子类的初始化加载呢?

6、根据类加载器加载类的初始化原理,推断以下代码的输入结果为?


1、JAVA的类加载期负责整个生命周期内的class的初始化和加载工作,就虚拟机的规范来说,以下代码会输出什么结果?

public class Test {
    public static void main(String[] args) {
        System.out.println(Test2.a);
    }
}
class Test2{
    public static final String a="test";

    static {
        System.out.print("OK");
    }
}
  • 结果:test
  • 解释:被 static final 修饰的变量,在编译期就已经完成真正的赋值。此时不需要对类 Test2 进行初始化即可读取。

2、JAVA的类加载期负责整个生命周期内的class的初始化和加载工作,就虚拟机的规范来说,以下代码会输出什么结果?

public class Test {

    public static void main(String[] args) {
        System.out.println(Test2.a);
    }
}

class Test2 {
    public static final String a = new String("test");

    static {
        System.out.print("OK");
    }
}
  • 结果:OKtest
  • 解释:因为存在 new String(""),这将强制对类 Test2进行初始化操作,此时先执行了 static 块中的代码,再进行对象的输出。

3、这个同2

public class Test {

    public static void main(String[] args) {
        System.out.println(Test2.a);
    }

}
class Test2{
    static {
        System.out.print("OK");
    }

    public static final String a=new String("test");

}

4、继承是JAVA语言的一个特性,针对类的继承,虚拟机会如何进行父类和子类的初始化加载呢?

public class Test {

    public static void main(String[] args) {
        System.out.print(B.c);
    }
}

class A {
    static {
        System.out.print("A");
    }
}

class B extends A{
    static {
        System.out.print("B");
    }
    public final static String c = "C";
}
  • 结果:C
  • 解释:因为变量 c 是 static final 类型,编译期即完成真正赋值,可以使用,此时调 B.c 不需要对类 B进行初始化即可使用c。

5、继承是JAVA语言的一个特性,针对类的继承,虚拟机会如何进行父类和子类的初始化加载呢?

public class Test {

    public static void main(String[] args) {
        System.out.print(B.c);
    }
}

class A {
    public static String c = "C";

    static {
        System.out.print("A");
    }
}

class B extends A {
    static {
        System.out.print("B");
    }
}
  • 结果:AC
  • 解释:调用 B.c 时,由于 B 有父类 A,故先对 A 进行初始化,于是先执行输出 A。A 初始化完毕后,此时c是可直接使用的,而B 继承了A的变量c,也可直接使用。所以不用对类 B 进行初始化。

6、根据类加载器加载类的初始化原理,推断以下代码的输入结果为?

public class Test {

    public static void main(String[] args) throws Exception {
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        Class clazz = classLoader.loadClass("A");
        System.out.print("Test");
        clazz.forName("A");
    }
}

class A {
    static {
        System.out.print("A");
    }
}
  • 结果:TestA
  • 解释:这是 ClassLoader 和 Class.forName() 加载类时的区别,我们看源码即可:即 Class.forName() 会强制初始化, loadClass 并不会进行初始化。所以先输出 Test,再输出 A。
/*
* A call to {@code forName("X")} causes the class named
* {@code X} to be initialized.
*/
public static Class<?> forName(String className)
            throws ClassNotFoundException {
    Class<?> caller = Reflection.getCallerClass();
    return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}


public Class<?> loadClass(String name) throws ClassNotFoundException {
    return loadClass(name, false);
}
发布了95 篇原创文章 · 获赞 16 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/tiankong_12345/article/details/89218728