类加载及初始化顺序例题

目录

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);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值