目录
1、JAVA的类加载期负责整个生命周期内的class的初始化和加载工作,就虚拟机的规范来说,以下代码会输出什么结果?
2、JAVA的类加载期负责整个生命周期内的class的初始化和加载工作,就虚拟机的规范来说,以下代码会输出什么结果?
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);
}