java中class.forName()和classLoader均可用來對類進行加載。
class.forName()前者除了將類的.class文件加載到jvm中以外,還會對類進行解釋,執行類中的static塊。
而classLoader只幹一件事情,就是將.class文件加載到jvm中,不會執行static中的內容,只有在newInstance纔會去執行static塊。
Class.forName(name, initialize, loader)帶參函數也可控制是否加載static塊。而且只有調用了newInstance()方法採用調用構造函數,建立類的對象java
看下Class.forName()源碼app
[java] view plain copyjvm
- //Class.forName(String className) 這是1.8的源碼
- public static Class<?> forName(String className) throws ClassNotFoundException {
- Class<?> caller = Reflection.getCallerClass();
- return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
- }
- //注意第二個參數,是指Class被loading後是否是必須被初始化。 不初始化就是不執行static的代碼即靜態代碼
而後就是,測試代碼證實上面的結論是OK的,以下:函數
[java] view plain copy測試
- package com.lxk.Reflect;
-
- /**
- * Created by lxk on 2017/2/21
- */
- public class Line {
- static {
- System.out.println("靜態代碼塊執行:loading line");
- }
- }
[java] view plain copyspa
- package com.lxk.Reflect;
-
- /**
- * Created by lxk on 2017/2/21
- */
- public class Point {
- static {
- System.out.println("靜態代碼塊執行:loading point");
- }
- }
[java] view plain copy.net
- package com.lxk.Reflect;
-
- /**
- * Class.forName和classloader的區別
- * <p>
- * Created by lxk on 2017/2/21
- */
- public class ClassloaderAndForNameTest {
- public static void main(String[] args) {
- String wholeNameLine = "com.lxk.Reflect.Line";
- String wholeNamePoint = "com.lxk.Reflect.Point";
- System.out.println("下面是測試Classloader的效果");
- testClassloader(wholeNameLine, wholeNamePoint);
- System.out.println("----------------------------------");
- System.out.println("下面是測試Class.forName的效果");
- testForName(wholeNameLine, wholeNamePoint);
-
- }
-
- /**
- * classloader
- */
- private static void testClassloader(String wholeNameLine, String wholeNamePoint) {
- Class<?> line;
- Class<?> point;
- ClassLoader loader = ClassLoader.getSystemClassLoader();
- try {
- line = loader.loadClass(wholeNameLine);
- point = loader.loadClass(wholeNamePoint);
- //demo = ClassloaderAndForNameTest.class.getClassLoader().loadClass(wholeNamePoint);//這個也是能夠的
- System.out.println("line " + line.getName());
- System.out.println("point " + point.getName());
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Class.forName
- */
- private static void testForName(String wholeNameLine, String wholeNamePoint) {
-
- try {
- Class line = Class.forName(wholeNameLine);
- Class point = Class.forName(wholeNamePoint);
- System.out.println("line " + line.getName());
- System.out.println("point " + point.getName());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
-
- }
執行結果以下:對象
![](http://static.javashuo.com/static/loading.gif)
備註:blog
根據運行結果,能夠看到,classloader並無執行靜態代碼塊,如開頭的理論所說。ip
而下面的Class.forName則是夾在完以後,就裏面執行了靜態代碼塊,能夠看到,2個類,line和point的靜態代碼塊執行結果是一塊兒的,而後纔是各自的打印結果。
也說明上面理論是OK的。
更新於2017/06/20
由於看到有小夥伴有疑問,我就把本身之前的代碼拿出來再次測試一遍,發現結果仍然是相同的。
可是,由於個人Javabean model又經歷了其餘的測試,因此,兩個model內部的代碼稍有變化,
而後,還真就測試出來了不同的地方。
這估計是其餘理論所沒有的。具體看下面的代碼吧。
只是修改了Line的代碼,添加了幾個靜態的方法和變量。
[java] view plain copy
- package com.lxk.reflect;
-
- /**
- * Created by lxk on 2017/2/21
- */
- public class Line {
- static {
- System.out.println("靜態代碼塊執行:loading line");
- }
-
- public static String s = getString();
-
- private static String getString() {
- System.out.println("給靜態變量賦值的靜態方法執行:loading line");
- return "ss";
- }
-
- public static void test() {
- System.out.println("普通靜態方法執行:loading line");
- }
-
- {
- System.out.println("要是普通的代碼塊呢?");
- }
-
- public Line() {
- System.out.println("構造方法執行");
- }
- }
能夠看到,除了原來的簡單的一個靜態代碼塊之外,我又添加了構造方法,靜態方法,以及靜態變量,且,靜態變量被一個靜態方法賦值。
而後,看執行結果。
稍有不一樣。
![](http://static.javashuo.com/static/loading.gif)
除了,靜態代碼塊的執行外,居然還有一個靜態方法被執行,就是給靜態變量賦值的靜態方法被執行了。
這個估計是之前沒人發現的吧。
因此
上面的結論,就能夠進一步的修改啦。
也許,這個執行的也叫,static塊呢。