类的主动使用和被动使用
【类的主动使用和被动使用】即判断是否执行
被动使用有可能会加载类(JVM规范里没有说明),根据不同虚拟机实现,如果在加载的过程中,遇到了.class文件的缺失或者存在错误,类加载器只会在首次主动使用它们时才会报错,如果一直没有主动使用,则不会报错
主动
一,使用new关键字或者通过反射、克隆、反序列化
二,调用类的静态方法。
三,当使用类、接口的静态字段时(final修饰特殊考虑)。
四,当使用java.lang.reflect包中的方法反射类的方法时。
五,当初始化子类时,如果发现其父类还没有进行过初始化,则需要先触发父类的初始化
interface Parent {
Thread thread = new Thread(){ //匿名内部类
{
System.out.println("Thread...Parent");
}
};
}
class Child implements Parent {
public static int b = 5;
}
public class Test04 {
public static void main(String[] args) {
System.out.println(Child.b);
}
}
//接口继承或者实现接口类,只有当程序首次使用特定接口的静态字段时,才会导致该接口的初始化,而且是引用类型的
//例子中初始化Chlid但并没有初始化父接口。
六,如果一个接口定义了default方法,那么直接实现或者间接实现该接口的类的初始化,该接口要在其之前被初始化。
interface Parent {
Thread thread = new Thread(){ //匿名内部类
{
System.out.println("Thread...Parent");
}
};
default void a(){
System.out.println("dafsdaf");
}
}
class Child implements Parent {
}
public class Test04 {
public static void main(String[] args) {
Child child=new Child();
}
}
七,jvm启动时被标明为启动类的类(如Java Test、main方法所在的类)
八,动态语言,当初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向的方法所在类。
被动
一,static final的常量
class F{
static final int count = 1;
static{
System.out.println("Initialize class F");
}
}
public class Test6 {
public static void main(String[] args) {
int x = F.count;
}
}
//static final的常量,F的class文件删掉,也不影响程序的正常执行,其在编译阶段就会存入调用类的常量池中
class F{
static final String s = UUID.randomUUID().toString();
static{
System.out.println("Initialize class F");
}
}
public class Test6 {
public static void main(String[] args) {
String x = F.s;
}
}
//运行期确定不是常量
二,当通过子类引用父类的静态变量,不会导致子类初始化
class Dfather{
static int count = 1;
static{
System.out.println("Initialize class Dfather");
}
}
class Dson extends Dfather{
static{
System.out.println("Initialize class Dson");
}
}
public class Test4 {
public static void main(String[] args) {
int x = Dson.count;
}
}
//会加载Dson,但不会初始化,不同虚拟机不同,可通过参数 -verbose:class查看
class C{
static int a=1;
static {
System.out.println("wdfghjkldfgh");
}
}
public class P extends C{
static {
System.out.println("fdsfsf");
}
public static void main(String[] args) {
System.out.println(P.a);
}
}
//注意若运行类直接继承则会初始化子类
三,通过数组定义类引用,不会触发此类的初始化
class E{
static{
System.out.println("Initialize class E");
}
}
public class Test5 {
public static void main(String[] args) {
E[] e = new E[10];
}
}
推荐阅读
- 继承及super关键字
- javaWeb|HTTPS 的加密流程(你值得拥有)
- Linux|Linux基本操作
- 数据结构|二叉树的经典面试题(你值得拥有)
- java编写代码小技巧_这8个写代码的技巧,让你快速提升工作效率
- 简洁的表白java_java简短表白代码怎么写(实操讲解)
- 校招|校招 --阶段一 系统编程】基于进程控制的实现简单的shell
- java代码优化_(提高Java代码质量)|25个优化Java代码的小技巧
- java|写简洁java代码的小技巧
- 封装及其作用Java