java反射中,Class.forName和classloader的區別

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

  1. //Class.forName(String className)  這是1.8的源碼  
  2.    public static Class<?> forName(String className) throws ClassNotFoundException {  
  3.        Class<?> caller = Reflection.getCallerClass();  
  4.        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);  
  5.    }  
  6. //注意第二個參數,是指Class被loading後是否是必須被初始化。 不初始化就是不執行static的代碼即靜態代碼  


而後就是,測試代碼證實上面的結論是OK的,以下:函數

 

[java] view plain copy測試

  1. package com.lxk.Reflect;  
  2.   
  3. /** 
  4.  * Created by lxk on 2017/2/21 
  5.  */  
  6. public class Line {  
  7.     static {  
  8.         System.out.println("靜態代碼塊執行:loading line");  
  9.     }  
  10. }  

 

 

 

[java] view plain copyspa

  1. package com.lxk.Reflect;  
  2.   
  3. /** 
  4.  * Created by lxk on 2017/2/21 
  5.  */  
  6. public class Point {  
  7.     static {  
  8.         System.out.println("靜態代碼塊執行:loading point");  
  9.     }  
  10. }  

 

[java] view plain copy.net

  1. package com.lxk.Reflect;  
  2.   
  3. /** 
  4.  * Class.forName和classloader的區別 
  5.  * <p> 
  6.  * Created by lxk on 2017/2/21 
  7.  */  
  8. public class ClassloaderAndForNameTest {  
  9.     public static void main(String[] args) {  
  10.         String wholeNameLine = "com.lxk.Reflect.Line";  
  11.         String wholeNamePoint = "com.lxk.Reflect.Point";  
  12.         System.out.println("下面是測試Classloader的效果");  
  13.         testClassloader(wholeNameLine, wholeNamePoint);  
  14.         System.out.println("----------------------------------");  
  15.         System.out.println("下面是測試Class.forName的效果");  
  16.         testForName(wholeNameLine, wholeNamePoint);  
  17.   
  18.     }  
  19.   
  20.     /** 
  21.      * classloader 
  22.      */  
  23.     private static void testClassloader(String wholeNameLine, String wholeNamePoint) {  
  24.         Class<?> line;  
  25.         Class<?> point;  
  26.         ClassLoader loader = ClassLoader.getSystemClassLoader();  
  27.         try {  
  28.             line = loader.loadClass(wholeNameLine);  
  29.             point = loader.loadClass(wholeNamePoint);  
  30.             //demo = ClassloaderAndForNameTest.class.getClassLoader().loadClass(wholeNamePoint);//這個也是能夠的  
  31.             System.out.println("line   " + line.getName());  
  32.             System.out.println("point   " + point.getName());  
  33.         } catch (ClassNotFoundException e) {  
  34.             e.printStackTrace();  
  35.         }  
  36.     }  
  37.   
  38.     /** 
  39.      * Class.forName 
  40.      */  
  41.     private static void testForName(String wholeNameLine, String wholeNamePoint) {  
  42.   
  43.         try {  
  44.             Class line = Class.forName(wholeNameLine);  
  45.             Class point = Class.forName(wholeNamePoint);  
  46.             System.out.println("line   " + line.getName());  
  47.             System.out.println("point   " + point.getName());  
  48.         } catch (Exception e) {  
  49.             e.printStackTrace();  
  50.         }  
  51.     }  
  52.   
  53.   
  54. }  


執行結果以下:對象

 

 

備註:blog

根據運行結果,能夠看到,classloader並無執行靜態代碼塊,如開頭的理論所說。ip

而下面的Class.forName則是夾在完以後,就裏面執行了靜態代碼塊,能夠看到,2個類,line和point的靜態代碼塊執行結果是一塊兒的,而後纔是各自的打印結果。

也說明上面理論是OK的。

 

更新於2017/06/20

由於看到有小夥伴有疑問,我就把本身之前的代碼拿出來再次測試一遍,發現結果仍然是相同的。

可是,由於個人Javabean model又經歷了其餘的測試,因此,兩個model內部的代碼稍有變化,

而後,還真就測試出來了不同的地方。

這估計是其餘理論所沒有的。具體看下面的代碼吧。

只是修改了Line的代碼,添加了幾個靜態的方法和變量。

 

[java] view plain copy

  1. package com.lxk.reflect;  
  2.   
  3. /** 
  4.  * Created by lxk on 2017/2/21 
  5.  */  
  6. public class Line {  
  7.     static {  
  8.         System.out.println("靜態代碼塊執行:loading line");  
  9.     }  
  10.   
  11.     public static String s = getString();  
  12.   
  13.     private static String getString() {  
  14.         System.out.println("給靜態變量賦值的靜態方法執行:loading line");  
  15.         return "ss";  
  16.     }  
  17.   
  18.     public static void test() {  
  19.         System.out.println("普通靜態方法執行:loading line");  
  20.     }  
  21.   
  22.     {  
  23.         System.out.println("要是普通的代碼塊呢?");  
  24.     }  
  25.   
  26.     public Line() {  
  27.         System.out.println("構造方法執行");  
  28.     }  
  29. }  

 

 

能夠看到,除了原來的簡單的一個靜態代碼塊之外,我又添加了構造方法,靜態方法,以及靜態變量,且,靜態變量被一個靜態方法賦值。

而後,看執行結果。

稍有不一樣。

除了,靜態代碼塊的執行外,居然還有一個靜態方法被執行,就是給靜態變量賦值的靜態方法被執行了。

這個估計是之前沒人發現的吧。

因此

上面的結論,就能夠進一步的修改啦。

也許,這個執行的也叫,static塊呢。

相關文章
相關標籤/搜索