比较两种类加载方式-使用.class和Class.forName(String className)

1.请先看Demo:

class Initable1Parent {
	static {
		System.out.println("Initializing Initable1Parent...");
	}
}


class Initable2Parent {
	static {
		System.out.println("Initializing Initable2Parent...");
	}
}
class Initable1 extends Initable1Parent{
	static {
		System.out.println("Initializing Initable1...");
	}
}
class Initable2 extends Initable2Parent{
	static {
		System.out.println("Initializing Initable2...");
	}
}


public class InitializeDemo {
	@Test
	public void test01() throws Exception {
		//使用.class方式加载字节码
		Class initable1Clazz = Initable1.class;
		//使用Class.forName(String className)方式加载字节码
		Class initable2Clazz = Class.forName("com.tca.thinkInJava.chap14.test.Initable2");
	}
}

执行结果:

Initializing Initable2Parent...
Initializing Initable2...

可以看出:

使用.class方式加载类并没有对该类及其父类进行静态初始化(并没有执行Initable1Parent和Initable1的静态代码块),但是使用Class.forName(String className)方式则对该类和父类进行了静态初始化。

2. 再看Demo

class Mouse {
	public static final String type = "Mouse";
	static {
		System.out.println("Initializing Mouse...");
	}
}

class Cat {
	public static String type = "Cat";
	static {
		System.out.println("Initializing Cat...");
	}
}

public class InitializeDemo {
	
	@Test
	public void test02() {
		Class dogClazz = Mouse.class;
		System.out.println(Mouse.type);
		Class catClazz = Cat.class;
		System.out.println(Cat.type);
	}
}	

执行结果:

Mouse
Initializing Cat...
Cat

可以看出:

1. 使用.class方式加载字节码时,并没有对类进行静态初始化(因为没有执行static静态代码块,但是已经由类加载器进行了加载,且对静态成员变量分配了存储空间)

2. 对于静态成员变量,使用final修饰与未使用final修饰(静态常量与静态非常量)之间的区别:

  如果类中使用static和final修饰了,则该类在没有初始化时,也可以直接访问其静态常量。如Demo中的Mouse,并没有执行Mouse类的静态代码块,但依然可以访问静态常量type,但是没有final则不同,同样没有使用.class方式进行类加载时,即没有对类进行初始化时,我们直接访问Cat类的静态成员变量(非final修饰),会先对该Cat类进行初始化,才可以访问其静态成员变量type


猜你喜欢

转载自blog.csdn.net/tca0819/article/details/80548689
今日推荐