java反射詳解 (二)

 【案例】經過反射操做屬性html

  
  
  
  
  1. class hello { 
  2.     public static void main(String[] args) throws Exception { 
  3.         Class<?> demo = null
  4.         Object obj = null
  5.   
  6.         demo = Class.forName("Reflect.Person"); 
  7.         obj = demo.newInstance(); 
  8.   
  9.         Field field = demo.getDeclaredField("sex"); 
  10.         field.setAccessible(true); 
  11.         field.set(obj, "男"); 
  12.         System.out.println(field.get(obj)); 
  13.     } 
  14. }// end class 

 

【案例】經過反射取得並修改數組的信息:java

  
  
  
  
  1. import java.lang.reflect.*; 
  2. class hello{ 
  3.     public static void main(String[] args) { 
  4.         int[] temp={1,2,3,4,5}; 
  5.         Class<?>demo=temp.getClass().getComponentType(); 
  6.         System.out.println("數組類型: "+demo.getName()); 
  7.         System.out.println("數組長度  "+Array.getLength(temp)); 
  8.         System.out.println("數組的第一個元素: "+Array.get(temp, 0)); 
  9.         Array.set(temp, 0100); 
  10.         System.out.println("修改以後數組第一個元素爲: "+Array.get(temp, 0)); 
  11.     } 

 

【運行結果】: c++

數組類型: int 數組

數組長度  5 app

數組的第一個元素: 1 ide

修改以後數組第一個元素爲: 100工具

【案例】經過反射修改數組大小ui

  
  
  
  
  1. class hello{ 
  2.     public static void main(String[] args) { 
  3.         int[] temp={1,2,3,4,5,6,7,8,9}; 
  4.         int[] newTemp=(int[])arrayInc(temp,15); 
  5.         print(newTemp); 
  6.         System.out.println("====================="); 
  7.         String[] atr={"a","b","c"}; 
  8.         String[] str1=(String[])arrayInc(atr,8); 
  9.         print(str1); 
  10.     } 
  11.       
  12.     /** 
  13.      * 修改數組大小 
  14.      * */ 
  15.     public static Object arrayInc(Object obj,int len){ 
  16.         Class<?>arr=obj.getClass().getComponentType(); 
  17.         Object newArr=Array.newInstance(arr, len); 
  18.         int co=Array.getLength(obj); 
  19.         System.arraycopy(obj, 0, newArr, 0, co); 
  20.         return newArr; 
  21.     } 
  22.     /** 
  23.      * 打印 
  24.      * */ 
  25.     public static void print(Object obj){ 
  26.         Class<?>c=obj.getClass(); 
  27.         if(!c.isArray()){ 
  28.             return
  29.         } 
  30.         System.out.println("數組長度爲: "+Array.getLength(obj)); 
  31.         for (int i = 0; i < Array.getLength(obj); i++) { 
  32.             System.out.print(Array.get(obj, i)+" "); 
  33.         } 
  34.     } 

 

 

 

【運行結果】: this

數組長度爲: 15 spa

1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================

數組長度爲: 8

a b c null null null null null

 

動態代理

【案例】首先來看看如何得到類加載器:

  
  
  
  
  1. class test{ 
  2.       
  3. class hello{ 
  4.     public static void main(String[] args) { 
  5.         test t=new test(); 
  6.         System.out.println("類加載器  "+t.getClass().getClassLoader().getClass().getName()); 
  7.     } 

 

【程序輸出】:

類加載器  sun.misc.Launcher$AppClassLoader

其實在java中有三種類類加載器。

1Bootstrap ClassLoader 此加載器採用c++編寫,通常開發中不多見。

2Extension ClassLoader 用來進行擴展類的加載,通常對應的是jre\lib\ext目錄中的類

3AppClassLoader 加載classpath指定的類,是最經常使用的加載器。同時也是java中默認的加載器。

若是想要完成動態代理,首先須要定義一個InvocationHandler接口的子類,已完成代理的具體操做。

  
  
  
  
  1. package Reflect; 
  2. import java.lang.reflect.*; 
  3.   
  4. //定義項目接口 
  5. interface Subject { 
  6.     public String say(String name, int age); 
  7.   
  8. // 定義真實項目 
  9. class RealSubject implements Subject { 
  10.     @Override 
  11.     public String say(String name, int age) { 
  12.         return name + "  " + age; 
  13.     } 
  14.   
  15. class MyInvocationHandler implements InvocationHandler { 
  16.     private Object obj = null
  17.   
  18.     public Object bind(Object obj) { 
  19.         this.obj = obj; 
  20.         return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj 
  21.                 .getClass().getInterfaces(), this); 
  22.     } 
  23.   
  24.     @Override 
  25.     public Object invoke(Object proxy, Method method, Object[] args) 
  26.             throws Throwable { 
  27.         Object temp = method.invoke(this.obj, args); 
  28.         return temp; 
  29.     } 
  30.   
  31. class hello { 
  32.     public static void main(String[] args) { 
  33.         MyInvocationHandler demo = new MyInvocationHandler(); 
  34.         Subject sub = (Subject) demo.bind(new RealSubject()); 
  35.         String info = sub.say("Rollen"20); 
  36.         System.out.println(info); 
  37.     } 

 

 

【運行結果】:

Rollen  20

類的生命週期

在一個類編譯完成以後,下一步就須要開始使用類,若是要使用一個類,確定離不開JVM。在程序執行中JVM經過裝載,連接,初始化這3個步驟完成。

類的裝載是經過類加載器完成的,加載器將.class文件的二進制文件裝入JVM的方法區,而且在堆區建立描述這個類的java.lang.Class對象。用來封裝數據。 可是同一個類只會被類裝載器裝載之前

連接就是把二進制數據組裝爲能夠運行的狀態。

 

連接分爲校驗,準備,解析這3個階段

校驗通常用來確認此二進制文件是否適合當前的JVM(版本),

準備就是爲靜態成員分配內存空間,。並設置默認值

解析指的是轉換常量池中的代碼做爲直接引用的過程,直到全部的符號引用均可以被運行程序使用(創建完整的對應關係)

完成以後,類型也就完成了初始化,初始化以後類的對象就能夠正常使用了,直到一個對象再也不使用以後,將被垃圾回收。釋放空間。

當沒有任何引用指向Class對象時就會被卸載,結束類的生命週期

將反射用於工廠模式

先來看看,若是不用反射的時候,的工廠模式吧:

 

http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html

 

  
  
  
  
  1. interface fruit{ 
  2.     public abstract void eat(); 
  3.   
  4. class Apple implements fruit{ 
  5.     public void eat(){ 
  6.         System.out.println("Apple"); 
  7.     } 
  8.   
  9. class Orange implements fruit{ 
  10.     public void eat(){ 
  11.         System.out.println("Orange"); 
  12.     } 
  13.   
  14. // 構造工廠類 
  15. // 也就是說之後若是咱們在添加其餘的實例的時候只須要修改工廠類就好了 
  16. class Factory{ 
  17.     public static fruit getInstance(String fruitName){ 
  18.         fruit f=null
  19.         if("Apple".equals(fruitName)){ 
  20.             f=new Apple(); 
  21.         } 
  22.         if("Orange".equals(fruitName)){ 
  23.             f=new Orange(); 
  24.         } 
  25.         return f; 
  26.     } 
  27. class hello{ 
  28.     public static void main(String[] a){ 
  29.         fruit f=Factory.getInstance("Orange"); 
  30.         f.eat(); 
  31.     } 
  32.   

 

這樣,當咱們在添加一個子類的時候,就須要修改工廠類了。若是咱們添加太多的子類的時候,改的就會不少。

如今咱們看看利用反射機制:

  
  
  
  
  1. package Reflect; 
  2.   
  3. interface fruit{ 
  4.     public abstract void eat(); 
  5.   
  6. class Apple implements fruit{ 
  7.     public void eat(){ 
  8.         System.out.println("Apple"); 
  9.     } 
  10.   
  11. class Orange implements fruit{ 
  12.     public void eat(){ 
  13.         System.out.println("Orange"); 
  14.     } 
  15.   
  16. class Factory{ 
  17.     public static fruit getInstance(String ClassName){ 
  18.         fruit f=null
  19.         try
  20.             f=(fruit)Class.forName(ClassName).newInstance(); 
  21.         }catch (Exception e) { 
  22.             e.printStackTrace(); 
  23.         } 
  24.         return f; 
  25.     } 
  26. class hello{ 
  27.     public static void main(String[] a){ 
  28.         fruit f=Factory.getInstance("Reflect.Apple"); 
  29.         if(f!=null){ 
  30.             f.eat(); 
  31.         } 
  32.     } 

 

 

如今就算咱們添加任意多個子類的時候,工廠類就不須要修改。

 

上面的愛嗎雖然能夠經過反射取得接口的實例,可是須要傳入完整的包和類名。並且用戶也沒法知道一個接口有多少個可使用的子類,因此咱們經過屬性文件的形式配置所須要的子類。

下面咱們來看看: 結合屬性文件的工廠模式

首先建立一個fruit.properties的資源文件,

內容爲:

  
  
  
  
  1. apple=Reflect.Apple 
  2. orange=Reflect.Orange  

 

而後編寫主類代碼:

  
  
  
  
  1. package Reflect; 
  2.   
  3. import java.io.*; 
  4. import java.util.*; 
  5.   
  6. interface fruit{ 
  7.     public abstract void eat(); 
  8.   
  9. class Apple implements fruit{ 
  10.     public void eat(){ 
  11.         System.out.println("Apple"); 
  12.     } 
  13.   
  14. class Orange implements fruit{ 
  15.     public void eat(){ 
  16.         System.out.println("Orange"); 
  17.     } 
  18.   
  19. //操做屬性文件類 
  20. class init{ 
  21.     public static Properties getPro() throws FileNotFoundException, IOException{ 
  22.         Properties pro=new Properties(); 
  23.         File f=new File("fruit.properties"); 
  24.         if(f.exists()){ 
  25.             pro.load(new FileInputStream(f)); 
  26.         }else
  27.             pro.setProperty("apple""Reflect.Apple"); 
  28.             pro.setProperty("orange""Reflect.Orange"); 
  29.             pro.store(new FileOutputStream(f), "FRUIT CLASS"); 
  30.         } 
  31.         return pro; 
  32.     } 
  33.   
  34. class Factory{ 
  35.     public static fruit getInstance(String ClassName){ 
  36.         fruit f=null
  37.         try
  38.             f=(fruit)Class.forName(ClassName).newInstance(); 
  39.         }catch (Exception e) { 
  40.             e.printStackTrace(); 
  41.         } 
  42.         return f; 
  43.     } 
  44. class hello{ 
  45.     public static void main(String[] a) throws FileNotFoundException, IOException{ 
  46.         Properties pro=init.getPro(); 
  47.         fruit f=Factory.getInstance(pro.getProperty("apple")); 
  48.         if(f!=null){ 
  49.             f.eat(); 
  50.         } 
  51.     } 

下面這個是一個比較完整的反射工具類,用來得到一個類裏面屬性的具體信息

  
  
  
  
  1. package util; 
  2. import java.lang.reflect.*; 
  3. /** 
  4.  * 獲取Class的信息 
  5.  * 
  6.  */ 
  7. public class ClassInfo { 
  8.   //須要反射的JAVA類型 
  9.   private static Class reflectionClass; 
  10.   private static String[][] relation; 
  11.   private static String[] constructors; 
  12.   private static String[] methods; 
  13.   private static String[] fields; 
  14.    
  15.   //加載須要反射的類 
  16.   public static void load(String reflectionClassName) { 
  17.     try { 
  18.       reflectionClass = null
  19.       reflectionClass = Class.forName(reflectionClassName); 
  20.     } catch (ClassNotFoundException e) { 
  21.       System.err.println(e.getMessage()); 
  22.     } 
  23.   } 
  24.   //獲取類關係 
  25.   public static String[][] getRelation() { 
  26.     String superClassName = reflectionClass.getSuperclass().getSimpleName(); 
  27.     Class[] interfaceClass = reflectionClass.getInterfaces(); 
  28.     if(superClassName == null
  29.       superClassName = "Have not super class!"
  30.     if (reflectionClass.getInterfaces().length == 0) { 
  31.       relation = new String[2][1]; 
  32.       relation[1][0] = "Have not interface!"
  33.     }else { 
  34.       relation = new String[2][reflectionClass.getInterfaces().length]; 
  35.       for (int i = 0; i < interfaceClass.length; i++) { 
  36.         relation[1][i] = interfaceClass[i].getName(); 
  37.         System.out.println( "interfaceClass:"+relation[1][i] ); 
  38.       } 
  39.     } 
  40.     relation[0][0] = superClassName; 
  41.     System.out.println( "superClassName:"+superClassName ); 
  42.     return relation; 
  43.   } 
  44.   
  45.   //獲取構造方法 
  46.   public static String[] getConstructors() { 
  47.     Constructor[] constructor = reflectionClass.getDeclaredConstructors(); 
  48.     constructors = new String[constructor.length]; 
  49.     for (int i = 0; i < constructor.length; i++) { 
  50.       Class[] paramType = constructor[i].getParameterTypes(); 
  51.       String param = ""
  52.       for (int j = 0; j < paramType.length; j++) { 
  53.         param += paramType[j].getSimpleName().toString() + " "
  54.       } 
  55.       constructors[i] = constructor[i].getName().toString()  
  56.                 + "(" + param + ")"
  57.       System.out.println("constructor:"+ constructors[i] ); 
  58.     } 
  59.     return constructors; 
  60.   } 
  61.   //獲取類方法 
  62.   public static String[] getMethods() { 
  63.     Method[] method = reflectionClass.getDeclaredMethods(); 
  64.     methods = new String[method.length]; 
  65.     for (int i = 0; i < method.length; i++) { 
  66.       Class[] paramType = method[i].getParameterTypes(); 
  67.       String param = ""
  68.       for (int j = 0; j < paramType.length; j++) { 
  69.         param += paramType[j].getSimpleName().toString() + " "
  70.       } 
  71.       methods[i] = method[i].getName().toString()  
  72.             + "(" + param + ")"
  73.       System.out.println("method:"+ methods[i]); 
  74.     } 
  75.     return methods; 
  76.   } 
  77.   //獲取類屬性 
  78.   public static String[] getFields() { 
  79.     Field[] field = reflectionClass.getDeclaredFields(); 
  80.     fields = new String[field.length]; 
  81.     for (int i = 0; i < field.length; i++) { 
  82.     field[i].setAccessible( true ); //容許訪問私有屬性 
  83.       fields[i] = field[i].toGenericString(); 
  84.       String type=field[i].getGenericType().toString(); 
  85.       System.out.println("fields:"+fields[i]+"   type:"+type); 
  86.     } 
  87.     return fields; 
  88.   } 
  89.    
  90.   //私有方法,被外部調用 
  91.   private void testInvoke() { 
  92.     System.out.println("invoke!"); 
  93.   } 
  94.   private void testInvoke(String str) { 
  95.     System.out.println("invoke!:" + str); 
  96.   } 
相關文章
相關標籤/搜索