Java編程之反射-demo

       本節寫了個Demo測試反射機制的主要方法,有些細節的東西沒有再具體細化,把反射的主要功能都實現了一遍,代碼如下:

public class TestReflect
{
	public static void main(String[] args) 		
	{
		//測試所有構造函數
		getAllConstructors();
		
		//測試私有構造函數
		getPrivateConstructor();
		
		//測試運行私有方法
		getPrivateMethod();
		
		//測試獲取和設置屬性
		getFields();
	}

	private static void getFields()
	{
		try
		{
			//加載類對象
			Class<?> c = Class.forName("reflect.domain.Human");
			//實例化Human對象
			Human human = (Human) c.newInstance();
			//獲得Human對象所有屬性
			Field[] fields = c.getDeclaredFields();
			for(int i = 0, size = fields.length; i < size; i++)
			{
				Field field = fields[i];
				System.out.println(field.toGenericString());
				String name = field.getName();
				//轉換將屬性名首字母大寫
				if(!Character.isUpperCase(name.charAt(0)))
				{		       
		                    name = (new StringBuilder()).append(Character.toUpperCase(name.charAt(0))).append(name.substring(1)).toString();
				}
				//拼接獲得屬性設置方法名
				String setMethod = "set" + name;
				//獲得屬性設置Method
				Method method = c.getDeclaredMethod(setMethod, new Class[]{String.class});
				method.setAccessible(true);
				//執行屬性設置方法
				method.invoke(human, new Object[]{"ss"});
			}
			human.introdude();
		}
		catch(Exception e)
		{
			//todo
		}		
	}

	private static void getPrivateMethod()
	{
		try
		{
			Class<?> c = Class.forName("reflect.domain.Human");
			Human human = (Human) c.newInstance();
			//獲得指定方法名和參數類型的方法
			Method method = c.getDeclaredMethod("privateMethod", new Class[]{});
			//設置可訪問
			method.setAccessible(true);
			//觸發執行該方法
			method.invoke(human, new Object[]{});
		}
		catch(Exception e)
		{
			//todo
		}		
	}

	private static void getPrivateConstructor()
	{
		try
		{
			Class<?> c = Class.forName("reflect.domain.Human");
			//獲得指定參數類型的構造函數
			Constructor cons = c.getDeclaredConstructor(new Class[]{String.class});
			//設置可訪問
			cons.setAccessible(true);
			//初始化實例,根據傳入的參數初始化
			Human human = (Human) cons.newInstance(new Object[]{"William"});
			//執行對象方法
			human.publicMethod();
			human.introdude();
		}
		catch(Exception e)
		{
			//todo
		}
		
	}

	private static void getAllConstructors()
	{
		try
		{
			Class<?> c = Class.forName("reflect.domain.Human");	
			//獲得所有構造函數
			Constructor[] constructors = c.getDeclaredConstructors();
			Human human = null;
			for(int i = 0, size = constructors.length; i < size; i++)
			{
				Constructor cons = constructors[i];
				cons.setAccessible(true);
				//獲得構造函數完整簽名
				String consName = cons.toGenericString();
				//獲得該構造函數的參數
				String[] arg1 = consName.split("\\(");
				String[] arg2 = arg1[1].split("\\)");				
				if(0 == arg2.length)
				{
					//如果參數爲0,調用無參構造函數實例化
					human = (Human) cons.newInstance();
					human.introdude();
				}
				else
				{	
					//否則根據參數個數和類型分別實例化,如果不知道參數類型,也可以用反射機制獲得,這裏不再麻煩
					String[] args = arg2[0].split(",");
					if(1 == args.length)
					{
						human = (Human) cons.newInstance(new Object[]{"Ann"});
						human.introdude();
					}
					else if(2 == args.length)
					{
						human = (Human) cons.newInstance(new Object[]{"Ann", "female"});
						human.introdude();
					}	
				}			
			}
		}
		catch(Exception e)
		{
			//todo
		}		
	}
}

         反射機制允許一個類使用另一個類,即使當前者被編譯的時候後者還根本不存在。然後,這種能力也要付出代價:

      1.喪失了編譯時類型檢查的好處,包括異常檢查。如果程序試圖用反射方式調用不存在或不可訪問的方法,在運行時它可能會失敗,因此需要做好防護措施;

      2.執行反射訪問所需要的代碼非常笨拙和冗長。編寫乏味,閱讀困難;

      3.性能損失。反射方法調用比普通方法調用慢很多。

      以上來自<<Effective Java>>。

      因此,在普通的方法調用中不需要使用反射,在一些複雜程序中,而且需要使用在編譯時無法知道的對象時,才考慮使用反射機制。

      反射是一些框架技術的核心,比如Spring,Struts2等,對於反射的原理還需要進一步掌握。

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