java中的反射技術

1: java中的反射機制:

 a)在Java 運行時 環境中,對任意一個類, 可以知道這個類所有的屬性和方法。

b)任意一個對象,可以動態地獲取類的信息,然後調用類中的方法, 也是基於java中的反射。

2: java中反射能夠提供的功能:

a)在運行時判斷任意一個對象所屬的類.

b)在運行時構造任意一個類的對象.

c)在運行時調用任意一個對象的方法.

3 :Java 反射相關的API簡介:

位於java.lang.reflect包中

--Class類:代表一個類

 --Filed類:代表類的成員變量

--Method類:代表類的方法

--Constructor類:代表類的構造方法

Class類:類的實例表示正在運行的java 應用程序中的類和接口。

    來個小例子:

編寫測試類的代碼:

import java.awt.event.ActionListener;  
import java.awt.event.ActionEvent;  
class A extends Object implements ActionListener{  
private int a = 3;  
public Integer b = new Integer(4);  
public A(){}  
public A(int id,String name){}  
public int abc(int id,String name){return 0;}  
public void actionPerformed(ActionEvent e){}  
}  

1)獲取Class A 類中的屬性。

//用來獲取A類中的屬性和屬性值。
public class GetAattribute {
	 public static void main(String[] args) {
		 A a = new A();  
		 Class aClass = a.getClass();  
		 try{  
		    System.out.println("反射類中所有公有的屬性");  
		    Field[] fpublic  =aClass.getFields();  
		    for(int j=0;j<fpublic.length;j++){  
		     Class cl = fpublic[j].getType();  
		     System.out.println("fb:"+cl);  
		   }  
		    System.out.println("反射類中所有的屬性");  
		 Field[] fall = aClass.getDeclaredFields();  
		   for(int j=0;j<fall.length;j++){  
		       Class cl = fall[j].getType();  
		       System.out.println("fa:"+cl);  
		 }  
		   System.out.println("反射類中私有屬性的值");  
		
		 Field f = aClass.getDeclaredField("a");  
		 f.setAccessible(true);  
		 Integer i = (Integer)f.get(a);  
		 System.out.println(i); 
		/* Field fInteger=aClass.getDeclaredField("b");
		 fInteger.setLong("b", 10L);
		 fInteger.setAccessible(true);
		 System.out.println(fInteger);*/
		 }catch(Exception e){  
		 e.printStackTrace();  
		 }  
	}
}

     這裏用到了兩個方法,getFields()、getDeclaredFields(),它們分別是用來獲取反射類中所有公有屬性和反射類中所有的屬性的方法。另外還有getField(String)和getDeclaredField(String)方法都是用來過去反射類中指定的屬性的方法,要注意的是getField方法只能取到反射類中公有的屬性,而getDeclaredField方法私有公共的都能夠取到;

     這裏還用到了Field 類的setAccessible方法,它是用來設置是否有權限訪問反射類中的私有屬性的,只有設置爲true時纔可以訪問,默認爲false。另外 Field類還有set(Object AttributeName,Object value)方法,可以改變指定屬性的值。 

2)如何獲取Class A類中的構造方法:

//獲取A類中的構造函數, 以及構造函數的類型
public class GetAconstructor {
	public static void main(String[] args) {  
		A a = new A();  
		printConstructors(a);  
		}
     
	public static void printConstructors(A a) {  
		Class aClass = a.getClass();  
		//獲取指定類的類名  
		String className = aClass.getName();  
		System.out.println("獲取A類的名字:"+className);
	try {  
		//獲取指定類的構造方法  , 這個獲取的是有參數的構造函數。
		Constructor[] theConstructors = aClass.getConstructors();  
		for(int i=0; i<theConstructors.length; i++) {  
		  //獲取構造函數 
		  Class[] parameterTypes = theConstructors[i].getParameterTypes(); 
		  System.out.print(className + "(");
		    for(int j=0; j<parameterTypes.length; j++)  
		      System.out.print(parameterTypes[j].getName() + " ");  
		        System.out.println(")");  
		    }  
		 }catch(Exception e) {  
		  e.printStackTrace();  
		}  
	}  
}
用getConstructors()方法獲取了反射類的構造方法的集合,並用Constructor類的getParameterTypes()獲取該構造方法的參數。 

3)獲取一下反射類Class A 的父類和接口:

//獲取A類的父類和接口
public class GetAparentClassAndinterface {
	
	
	public static void main(String[] args) throws Exception {  
		A aClass = new A();  
		printInterfaceNames(aClass);  
	  }  
	public static void printInterfaceNames(Object o) {  
		Class aClass = o.getClass();  
		//獲取反射類A的接口  
		Class[] theInterfaces = aClass.getInterfaces();  
		for(int i=0; i<theInterfaces.length; i++){  
		System.out.println(theInterfaces[i].getName());  
		}
		//獲取反射類A的父類(超類)  
		Class theparentclass = aClass.getSuperclass();  
		System.out.println(theparentclass.getName());  
		}
 }
只是用Class類的getInterfaces()方法獲取反射類的所有接口,由於接口可以有多個,所以它返回一個 Class數組。用getSuperclass()方法來獲取反射類的父類(超類),由於一個類只能繼承自一個類,所以它返回一個Class對象。 

4)獲取反射類Class A 類中的方法:

//獲取反射類中的方法
public class getAmethods {
	
	public static void main(String[] args) {  
		A a = new A();  
		printMethods(a);  
	  } 
	public static void printMethods(Object o) {  
		Class aClass = o.getClass();
		System.out.println("反射類A:"+aClass);
		String className = aClass.getName();  
		System.out.println("反射類A的名字:"+className);
		//獲取反射類中的方法
		Method[] methods = aClass.getMethods();  
		for(int i=0; i<methods.length; i++) {  
		  //輸出方法的返回類型  
		  System.out.print(methods[i].getReturnType().getName());  
		    //輸出方法名  
		     System.out.print(" "+methods[i].getName()+"(");  
		    //獲取方法的參數  
		        Class[] parameterTypes = methods[i].getParameterTypes();  
		        for(int j=0; j<parameterTypes.length; j++){  
		         System.out.print(parameterTypes[j].getName());  
		         if(parameterTypes.length>j+1){  
		        	 System.out.print(",");  
		         } 
		     }  
		  System.out.println(")");  
	    }  
	}
 }
它只是獲得了反射類的所有方法,包括繼承自它父類的方法。然後獲取方法的返回類型、方法名和方法參數。 

5)獲取反射類的屬性、構造方法、父類、接口和方法之後就可以幫我們創建對象了。

//我們獲取了反射類的屬性、構造方法、父類、接口和方法,就可以創建對象了
public class GetObject {
	
	public Object getObject(String cName,String MethodName,String[] type,String[] param){  
		Object retobj = null;  
		try {  
		        //加載指定的Java類  
		            Class cls = Class.forName(cName);  
		            //獲取指定對象的實例  
		            Constructor ct = cls.getConstructor(null);  
		            Object obj = ct.newInstance(null);  
		            //構建方法參數的數據類型  
		            Class partypes[] = this.getMethodClass(type);  
		            //在指定類中獲取指定的方法  
		            Method meth = cls.getMethod(MethodName, partypes);  
		            //構建方法的參數值  
		            Object arglist[] = this.getMethodObject(type,param);  
		            //調用指定的方法並獲取返回值爲Object類型  
		            retobj= meth.invoke(obj, arglist);  
		           }  
		          catch (Throwable e) {  
		            System.err.println(e);  
		        }  
		     return retobj;  
		}  
	
	//獲取參數類型Class[]的方法  
	public Class[] getMethodClass(String[] type){  
	  Class[] cs = new Class[type.length];  
	    for (int i = 0; i < cs.length; i++) {  
	      if(!type[i].trim().equals("")||type[i]!=null){  
	          if(type[i].equals("int")||type[i].equals("Integer")){  
	             cs[i]=Integer.TYPE;  
	             }
	           else if(type[i].equals("float")||type[i].equals("Float")){  
	           cs[i]=Float.TYPE;  
	             }
	           else if(type[i].equals("double")||type[i].equals("Double")){  
	           cs[i]=Double.TYPE;  
	             }
	           else if(type[i].equals("boolean")||type[i].equals("Boolean")){  
	          cs[i]=Boolean.TYPE;  
	             }
	           else{  
	          cs[i]=String.class;  
	           }  
	         }  
	      }  
	    return cs;  
	    }  
	//獲取參數Object[]的方法  
	public Object[] getMethodObject(String[] type,String[] param){  
	  Object[] obj = new Object[param.length];  
	   for (int i = 0; i < obj.length; i++) {  
	     if(!param[i].trim().equals("")||param[i]!=null){  
	       if(type[i].equals("int")||type[i].equals("Integer")){  
	               obj[i]= new Integer(param[i]);  
	            }
	       else if(type[i].equals("float")||type[i].equals("Float")){  
	               obj[i]= new Float(param[i]);  
	            }
	       else if(type[i].equals("double")||type[i].equals("Double")){  
	                obj[i]= new Double(param[i]);  
	            }
	       else if(type[i].equals("boolean")||type[i].equals("Boolean")){  
	              obj[i]=new Boolean(param[i]);  
	            }
	       else{  
	              obj[i] = param[i];  
	            }  
	          }  
	       }  
	   return obj;  
	 }
}
  getObject()方法接收的五個參數分別是,Java的類名,方法名,參數的類型和參數的值。 由於一些返回值處理沒處理好, main沒有測試起來, 還要多想想。

關於反射的總結:

a)反射提供一種動態鏈接程序組件的多功能方法,它允許程序創建和控制任何類的對象.

b)它使類和數據結構能按名稱動態檢索相關信息,並允許在運行着的程序中操作這些信息

c)但反射有兩個缺點:第一個是性能問題,用於字段和方法接入時反射要遠慢於直接代碼, 但是要是在使用反射的過程中,作爲程序運行中相對很少涉及的部分,緩慢的性能將不會是一個問題。


對反射的理解也不是很深, 在實際的開發中也用得,因此整理的這些, 對於最後一個getObject()方法,有一些參數轉換方面的有問題沒能進行main方法測試, 如果有大神可以幫我看看


來源:http://www.iteye.com/topic/137944





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章