天天看點

【反射學習總結(上)】

【一】Class類是什麼樣的類?

【二】Class類中包含了一些什麼樣的具體東西?

【三】定義Class類常用的三種方法是什麼?

【四】Class類對象中的原始類有幾種,分别是什麼?

【五】反射的基本定義,和Class類的具體關系是怎樣的?

首先

【一】:對Class類的定義:

我是這樣了解的,我們知道:對于java中一些基本資料類型,都可以用數組來存放;對于類對象呢,我們可以用集合來存放;數組和集合都可以比作成為一種形象直覺的容器,隻要把分類好的東西丢進去就OK了,就相當于現實生活中:裝液态東西的容器可以是瓶子,而裝固體的是框子的原理!

那麼這裡的Class類,具體又是什麼呢?它既不是瓶子,也不是框子,它其實就是現實生活中的描述這些液體,固體,瓶子,框子等等的一個統一的“物體類”。它的功能很強大,它承載着上述事物的具體共性:這個“物體類”包含了實體的名稱,實體的範圍,實體的屬性!

是以:在JAVA中也就不難以了解了:java中的Class類:是描述JAVA中各個類為同一類事物的這樣一個類

它的内容也很豐富:它的成分中包含了各類的名稱,各類的類屬性,各類所屬的包名,各類的字段名稱,各類的方法名稱等等……再說得形象點吧:我們常用的自定義Person類,String類,Collection接口中的類,這些等等都是屬于Class類吧!

【二】:是以對于其Class包含了什麼,通過上述知道:簡單一句話,就是包含JAVA中各類的各項共同成分的一個大空間。當然空間并不是零亂的,它主要有各類的包名稱清單,方法名稱清單,字段名稱清單等等!

【三】:定義Class類常用的三種方式:也就是讓Class類執行個體化的一種表現形式:

(1)類名.class 例如:

Class clss=String.class;

我的分析過程:我們知道:當一個類通過加載器加載到記憶體中的時候,它自動占用了記憶體中的一片儲存空間,該空間中的内容就是該類的位元組碼,當然,不同的類有着不同的位元組碼檔案。換句話說:就是該記憶體空間中的内容具體是不一樣的,我們把這個記憶體空間用一個具體的對象來表示,這對象就是Class類的具體執行個體化!它可以是String類的空間,也可以是集合的空間,甚至可以是自定義類的空間,要确定這個空間,也就是要明确該對象:我們就要做到一個具體的執行個體化才行,這裡如果知道了具體的類,直接用位元組碼就OK了!

(2)通過第一種建立方式之後,就能夠了解第二種了

那就是:對象名稱.getClass();這樣了解對簡單:就是既然該類對象都已經存在了,那麼直接通過對象就能找到屬于Class類的一個執行個體了:

例如:new String("abc").getClass();

(3)還有第三種方式:主要是把完整的類名目錄作為參數傳遞給JVM,簡單一點,就是在告訴JVM這個類的具體位址,包名是不行的,必須是具體的開發中具體的路徑!

例如:Class clss=Class.forName("java.util.regex.WkzTestDemo");

具體執行個體可以看我寫的代碼:注意通過在java api幫助文檔中的學習發現:這裡的第三種方法會抛出異常,要處理掉才行!

例如:

<span style="font-size:18px;">/*
關于Class類擷取其對象的三種方法:
*/
class ReflectDemo1 
{
	public static void main(String[] args) 
	{
		
		String str="wkzcrytal";
		Class cls1=str.getClass(); //第二種方法

		Class cls2=String.class; //第一種方法
		Class cls3=null;
		try
		{
			cls3=Class.forName("java.lang.String");//這裡用的String類型,是以forName中就用引入其java内部的位址就OK
		}
		catch (ClassNotFoundException e)
		{
		}
		
		sop(cls1==cls2); //true
		sop(cls2==cls3); //true
	}

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}</span>
           

【四】對于Class類中對基本的原始類有幾種:

Class類的原始類:一共有九種:8中是基本的資料類型,大家都知道,還有一種就是void類型

通過學習了,我們知道:在Class類中:

Class類的執行個體有一個重要的判斷是不是原始類的方法.Class執行個體.IsPrimitive();傳回内容是boolean類型,是就是true,不是就是false

例如就是以上面的代碼繼續:

<span style="font-size:18px;">/*
關于Class類擷取其對象的三種方法:
該類對象中原始的基本資料類型對象
*/
class ReflectDemo1 
{
	public static void main(String[] args) 
	{
		
		String str="abc";
		Class cls1=str.getClass();

		Class cls2=String.class;
		Class cls3=null;
		try
		{
			cls3=Class.forName("java.lang.String");
		}
		catch (ClassNotFoundException e)
		{
			
		}
		
		sop(cls1==cls2); //true
		sop(cls2==cls3); //true
		
		//void位元組碼是不是原始的資料類型對象
		sop(void.class.isPrimitive()); //true,因為在9種中,有void的基本資料類型對象
		sop(int.class.isPrimitive()); //true
		sop(int[].class.isPrimitive()); //false
		sop(String.class.isPrimitive()); //false
		sop(cls1.isPrimitive()); //false
		
		sop(int.class==Integer.TYPE);
		//true  組成Integer的基本資料類型對象是不是int.class


		sop(int.class==Integer.class);//false
	}

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}</span>
           

【五】知道了上面的内容,現在反射就非常好了解了:

反射就是:把各個java類中的成分全部映射到相應的java類中來。

例如:java類中的基本方法,映射到一個java類是:Method類

  java類中的構造方法,映射到一個java類是:Constructor類

 還有很多,例如類中的成員變量類:Field類等等……很多!

       話不多說:執行個體來啦:

<span style="font-size:18px;">/*
示範:通過反射的思想得到指定類中帶參數的構造方法去建立新的指定對象
用反射的思想去完成str的對象建立
String str=new String(new StringBuffer("abc"));
構造方法的類:Constructor
重點:
1.擷取構造函數類對象,很關鍵(編譯時段)
2.得到類構造函數是,還得把參數從新傳入(運作時段)
*/
import java.lang.reflect.*;
class ReflectDemo2 
{
	public static void main(String[] args) throws Exception
	{
		//這是用反射的機制去是做通過得到類的執行個體之後,再調用其方法
		//下面是通過執行個體擷取了String類中帶StringBuffer類型參數的構造方法
		Constructor cons=String.class.getConstructor(StringBuffer.class);
		//建立一個string的執行個體對象(通過該構造方法對象new出一個具體的執行個體來)
		String str=(String)cons.newInstance(new StringBuffer("abc"));

		//上述兩句相當于String str=new String(new StringBuffer("abc"));
		System.out.println(str); //abc
	}
}
</span>
           

重點:其實就是通過反射機制來完成一些所映射類中方法的調用等等……

再例如執行個體:下面是一個自定義的類,通過反射的機制擷取其類中的成員變量,【注意】類中的成員變量有私有的情況,應該怎樣解決!

/*
示範通過反射得到自定義類中的成員變量
成員變量類:Field
*/
import java.lang.reflect.*;
class PointTest
{
	private int x;
	public  int y;
	int z;

	PointTest(int x,int y)
	{
		this.x=x;
		this.y=y;
	}

	PointTest(int x,int y,int z)
	{
		this(x,y);
		this.z=z;
	}
}

class ReflectDemo3 
{
	public static void main(String[] args) throws Exception 
	{
		PointTest pt=new PointTest(3,9,6);

		//通過反射擷取成員變量y的方法:這裡是public修飾
		//這裡的y是public修飾時,能得到,如果不寫修飾符号,也不能得到
		//是以,我們知道這種方法隻針對public有效
		Field fieldY=pt.getClass().getField("y");
		int new_y=(int)fieldY.get(pt);//直接擷取
		System.out.println("y="+new_y); //

		//通過反射擷取成員變量x的方法:這裡是private修飾
		Field fieldX=pt.getClass().getDeclaredField("x");//擷取所有申明的字段x
		fieldX.setAccessible(true);//強制通路才能得到
		int new_x=(int)fieldX.get(pt);
		System.out.println("x="+new_x);
		
		//對于沒有修飾符的,直接得到所有申明的字段z就行
		Field fieldZ=pt.getClass().getDeclaredField("z");
		int new_z=(int)fieldZ.get(pt);//不用強制方法得到
		System.out.println("z="+new_z);
	}
}
           

注意其中private修飾的成員變量:應該用全部被聲明的方法才能擷取到該Field的執行個體對象,通過這個Field類的執行個體對象,将其設定為強制通路之後,才能通過get方法在被映射的執行個體對象中擷取到相應的成員變量值!

繼續閱讀