java高新技術_枚舉反射內省(黑馬程序員)

------- android培訓、java培訓、期待與您交流! ----------

我們在java的技術學習中要時刻注意新知識的學習

1.如何傳入多個從參數?這裏是指可變參數

我們知道1.可變參數只能出現在參數列表的最後。2.。。。位於類型與變量名之間,有無空格均可!

public static void TecDemo_1(int num,String... args)
	{
		System.out.println("一共有"+num+"個參數");
		for(String s:args)
		{
			System.out.print(s);
		}
	}
TecDemo_1(3,"i","love","java");

調用函數獲得結果:一共有3個參數ilovejava。本例說明了可變參數和java加強for的使用!

2.枚舉

枚舉是非常重要的我們可以再定義常量的時候,考慮枚舉的使用。我們爲了熟悉枚舉的使用,先定義一個自己的枚舉方式!

//下面是模擬Enum的實現
abstract class weekday
{
	private weekday() {}//在enum中枚舉量的構造方法都是私有的,
	public final static weekday mon = new weekday(){

		@Override
		public weekday nextDay() {
			return sun;
		}};//而且枚舉量都是常量。可直接引用
	public final static weekday sun = new weekday(){

		@Override
		public weekday nextDay() {
			// TODO Auto-generated method stub
			return mon;
		}};	
	//在枚舉中有一些特殊的方法感覺很難,往往把方法定義爲一個抽象的這樣就可以再
	//自己的匿名子類中複寫,比較方便
	public abstract weekday nextDay();
}

我們可以調用我們定義的

public static void TecDemo_2()
	{
		weekday fir = weekday.mon;
		System.out.println(fir);	//com.lxbTestfile.weekday$1@dc8569
		System.out.println(fir.nextDay());//com.lxbTestfile.weekday$2@1bab50a
		//由以上的結果可以看出來那幾個mon,sun都是作爲子類來實現的!
		//把父類定義爲抽象類並沒有什麼不可以的。
		//這種方法也是enum中的方式,要牢記!
	}

這樣的話我們再來使用enum來比較一下我們自己定義的。

//在枚舉中可以直接定義抽象類不用加abstract了
enum weekDay
{
	//這裏相當於是建立了一個子類的匿名對象;
	mon("this is mon"){	
		@Override
		public  weekDay nextDay()
		{
			return sun;
		}
	},fri("this is fir") {
		@Override
		public weekDay nextDay() {
			return mon;
		}
	},sun("this is sun") {
		@Override
		public weekDay nextDay() {
			return fri;
		}
	};//這就相當於定義的枚舉常量
	private String name = null;
	private weekDay(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return name;
	}
	//枚舉中增加自己的方法
	public abstract weekDay nextDay();
	
	
}

可以看到的是十分方便,還要注意的是weekDay繼承了Enum類是不可以再繼承其他的類!如果也其他需求的話繼承接口吧!

public static void TecDemo_3()
	{
		weekDay  myf = weekDay.mon;
		System.out.println(myf.name());//枚舉中自己的名稱函數
		System.out.println(myf.ordinal());//獲得在枚舉中的index
		System.out.println(myf.getName());//自己定的名稱函數
		System.out.println(myf.nextDay());
	}
這裏調用了函數來使用我們的枚舉類!

你把枚舉成員定義爲一個的時候,看看是什麼?好的,的確,枚舉可以作爲單例來使用!

3.我們來看一下反射,反射的意思就是把class中的東西映射爲可操作的方法;主要有構造函數Constructor,方法Method,字段Field。

如何獲得constructor呢?也就是如何獲得構造方法?

//下面是夠造class的3種方式:然後又獲得了構造方法!
		//Constructor myconstructor = String.class.getConstructor(StringBuilder.class);
		//Constructor myconstructor = "class".getClass().getConstructor(StringBuilder.class);
		Constructor myconstructor = Class.forName("java.lang.String").getConstructor(StringBuilder.class);
		String mystr = (String) myconstructor.newInstance(new StringBuilder("abc"));//如何讓調用構造方法!
		System.out.println(mystr);

上述例子中也說明了如何獲得class對象的3種方法:1.對象.getClass()。2.類名.Class。3.Class.forNAme("對象所在包")。

構造方法獲得後,調用newInstance()可以調用構造方法。產生對象!

如何獲得字段?

refPoint ref = new refPoint();
		Field myf = refPoint.class.getField("num2");//獲得字段的class反射
		myf.set(ref, "banana");//可以修改字段!
		String mystr2 = (String) myf.get(ref);//有反射獲得對象字段的值!
		System.out.println(mystr2);
		//下面爲暴力反射的例子	
		Field myf2 = ref.getClass().getDeclaredField("num1");
		myf2.setAccessible(true);//由於num1爲private所以要設爲可見!
		String mystr3 = (String) myf2.get(ref);
		System.out.println(mystr3);

首先來說明refPoint是什麼吧

class refPoint
{
	private String num1 = "mango";
	public  String num2 = "apple";
	public void sop(String[] str)
	{
		for(String s:str)
		System.out.println(s);
	}
}

獲取字段還是比較簡單的,調用getField方法就可以獲得某一個字段了,調用get或者是set就可以修改;

注意的是在對象中private字段是不可見的,我們可以用暴力反射來解決!

下面看一下獲得方法:

//在方法反射中要注意的是調用invoke方法就是調用原來的方法!
		Method mym = String.class.getMethod("charAt",int.class);
		System.out.println( mym.invoke("abs",1));
		 System.out.println( mym.invoke("abs",new Object[]{2}));
		 //如果參數方法第一個參數爲null認爲是靜態方法!
		 Method mym2 = Integer.class.getMethod("toString", null);
		 System.out.println(mym2.invoke(2, null));
		 //要注意的是在反射方法的時候如果傳入的是一個數組,那麼會有不同的現象
		 //也就是說如果是對象的數組要加(Object),以免java認爲傳入多個參數!
		 Method mym3 = ref.getClass().getMethod("sop", String[].class);
		 mym3.invoke(ref,(Object)new String[]{"hello","world"});

調用getMethod就可以了,要注意代碼註釋的傳入數組的時候要小心!

那麼如何反射數組呢?

//數組的class只和數組的類型和維度有關
		 int[] numbe = new int[]{1};//也就是說numb和number的getClass()是一樣的
		 int[] number = new int[]{1,2,3};
		 String[] strber = new String[]{"i","love","java"};
		 	//數組的反射是利用Array來實現的
		 System.out.println(Array.getLength(number));//獲取數組長度
		 System.out.println(Array.get(strber, 2));//獲取數組的成員

數組的反射是靠Array來實現的,注意一下Arrays。asList()方法也是很有用的!

4內省機制(introspector)是爲了方便處理javabean。如何利用內省來處理javaBean?首先來看一個javaBean

class loveperson
{
	public loveperson(String name,int age)
	{
		this.name = name;
		this.age =age;
	}
	private String name;
	private int age ;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}	
}

還是比較簡單的。如何在程序中處理呢?

public static void TecDemo_5() throws Exception 
	{
		//這是第一種方法操作javabean,用的是PropertyDescriptor對象
		loveperson p = new loveperson("lxb",15);
		PropertyDescriptor proDes = new PropertyDescriptor("name",p.getClass());//利用類和類的屬性名做參數生成一個對象
		Method m = proDes.getReadMethod();//那個獲取讀的方法
		Method m1 = proDes.getWriteMethod();//獲取寫的方法
		String myname = (String) m.invoke(p);//調用讀的方法
		m1.invoke(p,"bxl");//調用寫的方法
		System.out.println(myname);
		System.out.println(p.getName());
		
		//下面用一種老的方法來進行操作
		BeanInfo binfo = Introspector.getBeanInfo(p.getClass());//首先獲得一個beanInfo對象
		PropertyDescriptor[] pDes = binfo.getPropertyDescriptors();//通過beanInfo來獲得PropertyDescriptor!
		for(PropertyDescriptor pd:pDes)
		{
			if(pd.getName().equals("name"))
			{
				Method m3 = pd.getReadMethod();
				String myname2 = (String) m3.invoke(p);
				System.out.println(myname2);
			}
		}
	}

在代碼中我給除了兩種方法。推薦用第一種!第二種是十分繁瑣的,所以你要來接即可!

在內省中要合理運用PropertyDescriptor來處理!主要就是getReadMethod和getWriteMethod的使用



------- android培訓、java培訓、期待與您交流! ----------

發佈了27 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章