① java中反射實例類裝載的步驟及簡要闡述
java反射和類裝載
反射機制:
Person p=new Person();
這是什麼?當然是實例化一個對象了.可是這種實例化對象的方法存在一個問題,那就是必須要知道類名才可以實例化它的對象,這樣我們在應用方面就會受到限制.那麼有沒有這樣一種方式,讓我們不知道這個類的類名就可以實例化它的對象呢?Thank Goodness!幸虧我們用的是java, java就提供了這樣的機制.
1).java程序在運行時可以獲得任何一個類的位元組碼信息,包括類的修飾符(public,static等),基類(超類,父類),實現的介面,欄位和方法等信息.
2).java程序在運行時可以根據位元組碼信息來創建該類的實例對象,改變對象的欄位內容和調用對象方法.
這樣的機制就叫反射技術.可以想像光學中的反射,就像我們照鏡子,鏡子中又出現一個自己(比喻可能不太恰當,但是足以表達清楚意思了).反射技術提供了一種通用的動態連接程序組件的方法,不必要把程序所需要的目標類硬編碼到源程序中,從而使得我們可以創建靈活的程序.
反射的實現步驟( 不問不需要答) ,
1、獲取類的常用方式有三種: a) Class.forName("包名.類名"),最常用、推薦;b) 包名.類名.class 最簡捷;c) 對象.getClass 的方式獲得。
2、對象的實例化,上面已經獲取了類,只需要調用類的實例化方法,類.newInstance()便可。
3、獲取屬性和構造等,可以參考 JavaApi 的調用,類. getDeclaredFields,類. getConstructor(..)等。
Java的反射機制是通過反射API來實現的,它允許程序在運行過程中取得任何一個已知名稱的類的內部信息.反射API位於java.lang.reflect包中.主要包括以下幾類:
1).Constructor類:用來描述一個類的構造方法
2).Field類:用來描述一個類的成員變數
3).Method類:用來描述一個類的方法.
4).Modifer類:用來描述類內各元素的修飾符
5).Array:用來對數組進行操作.
Constructor,Field,Method這三個類都是JVM(虛擬機)在程序運行時創建的,用來表示載入類中相應的成員.這三個類都實現了java.lang.reflect.Member介面,Member介面定義了獲取類成員或構造方法等信息的方法.要使用這些反射API,必須先得到要操作的對象或類的Class類的實例.通過調用Class類的newInstance方法(只能調用類的默認構造方法)可以創建類的實例.這樣有局限性,我們可以先沖類的Class實例獲取類需要的構造方法,然後在利用反射來創建類的一個實例.
類載入機制:
類的載入機制可以分為載入-鏈接-初始化三個階段,鏈接又可以分為驗證、准備、解析三個過程。
載入:通過類的載入器查找並載入二進制位元組流的過程,在堆內存中的方法區生成 一個代表這個類的 java.lang.Class 對象,作為這個類的數據請求入口。(這里可以把上面類載入器載入文件的過程描述一下(參考版本一,不作重復))。
驗證:主要是對一些詞法、語法進行規范性校驗,避免對 JVM 本身安全造成危害; 比如對文件格式,位元組碼驗證,無數據驗證等。但驗證階段是非必須的,可以通過參數 設置來進行關閉,以提高載入的時效。
准備:對類變數分配內存,並且對類變數預初始化,初始化成數據類型的原始值, 比如 static int a=11,會被初始化成成 a=0;如果是 static double a =11,則會被初始化成 a=0.0; 而成員變數只會成實例化後的堆中初始化。
解析:把常量池中的符號引用轉換為直接引用的過程。
初始化:對類的靜態變數和靜態塊中的變數進行初始化。(上面的准備階段可以作為 預初始化,初始到變數類型的原值,但如果被 final 修飾會進行真正初始化)
上面載入、鏈接、初始化的各個階段並不是彼此獨立,而是交叉進行,這點很重要 。
***class.forName和 classloader的區別
Class.forName 和 ClassLoader 都是用來裝載類的,對於類的裝載一般為分三個階段載入、鏈接、編譯,它們裝載類的方式是有區別。
首先看一下 Class.forName(..),forName(..)方法有一個重載方法 forName(className,boolean,ClassLoader),它有三個參數,第一個參數是類的包路徑,第二個參數是 boolean
類型,為 true 地表示 Loading 時會進行初始化,第三個就是指定一個載入器;當你調用class.forName(..)時,默認調用的是有三個參數的重載方法,第二個參數默認傳入 true,第三個參數默認使用的是當前類載入時用的載入器。
ClassLoader.loadClass()也有一個重載方法,從源碼中可以看出它默認調的是它的重載 方法 loadClass(name, false),當第二參數為 false 時,說明類載入時不會被鏈接。這也是兩者之間最大區別,前者在載入的時候已經初始化,後者在載入的時候還沒有鏈接。如果你需要在載入時初始化一些東西,就要用 Class.forName 了,比如我們常用的驅動載入, 實際上它的注冊動作就是在載入時的一個靜態塊中完成的。所以它不能被 ClassLoader 載入代替。
② Java裡面反射的原理是什麼
java虛擬機運行時內存有個叫方法區,主要作用是存儲被裝載的類的類型信息。每裝載一個類的時候,java就會創建一個該類的Class對象實例。我們就可以通過這個實例,來訪問這個類的信息。
③ JAVA中反射是什麼
JAVA中反射是動態獲取信息以及動態調用對象方法的一種反射機制。
Java反射就是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;並且能改變它的屬性。而這也是Java被視為動態語言的一個關鍵性質。
Java反射的功能是在運行時判斷任意一個對象所屬的類,在運行時構造任意一個類的對象,在運行時判斷任意一個類所具有的成員變數和方法,在運行時調用任意一個對象的方法,生成動態代理。
(3)java反射子類擴展閱讀:
JAVA中反射實例:
1、Class superClass=clazz.getSuperclass();//獲取父類。
System.out.println("getSuperclass:"+superClass)。
2、Class[] interfaces=clazz.getInterfaces();//獲取實現介面。
System.out.println("getInterfaces:"+interfaces.length)。
3、Constructor[] cons=clazz.getConstructors();//構造方法。
System.out.println("getConstructors:"+cons.length)。
參考資料來源:網路: JAVA反射機制
④ java中的反射機制是什麼,有什麼作用啊
Method類中的方法的使用(含代碼和注釋):
getMethods()獲得本類及父類中的public許可權修飾**符方法
getDeclaredMethods()專門獲得調用該方法的對象的本類中的所有方法包括private許可權修飾符**的方法
getDeclaredMethod(Stringname,class<?>...parameterTypes)
第一個參數:方法的名稱
第二個參數:可變長度,寫你要查找的那個方法的參數類型列表.class
getParameterCount()得到方法的參數個數123456
packageLessonForReflection03;importjava.lang.reflect.Method;importjava.lang.reflect.Modifier;abstractclassCard{
privatevoidcreatRandomNumbers(intcount)//private關鍵字
{
}
publicvoidgetFullCardsNumbers(String[]random,Stringpre_numbers)
{
}
publicstaticvoidgetUserInfor()
{
}
(Stringtel);
(intsal1,intsal2),ArithmeticException;}publicclassMethodInforGetter{
publicstaticvoidmain(String[]args)
{
Class<?>c1=Card.class;
System.out.println("-------------------------");
Method[]m1=c1.getMethods();//getMethods()獲得本類及父類中的public方法!
for(Methodm:m1)
{
System.out.println(m);
}
System.out.println("-------------------------");
Method[]m2=c1.getDeclaredMethods();//getDeclaredMethods()專門獲得本類中的所有方法包括private!
for(Methodm:m2)
{
System.out.println(m);
}
System.out.println("-------------------------");
/*
*getDeclaredMethod(Stringname,class<?>...parameterTypes)
*第一個參數:方法的名稱
*第二個參數:可變長度,寫你要查找的那個方法的參數類型列表
*
*getParameterCount()得到方法的參數個數
*/
try
{
Methodm3=c1.getDeclaredMethod("getUserInfor");
System.out.println(m3);
//getParameterCount()方法,獲得方法參數個數
System.out.println(m3.getParameterCount());
System.out.println(Modifier.toString(m3.getModifiers()));//獲得方法修飾符
System.out.println(m3.getReturnType());
System.out.println("-------------------------");
Methodm4=c1.getDeclaredMethod("getUserInfor",int.class,int.class);
//getExceptionTypes()可以獲得初始化當前Method對象的給Class對象初始化的那個類的那個指定方法拋出的異常類型
Class<?>[]exception=m4.getExceptionTypes();
for(Class<?>e:exception)
{
System.out.println(e);
}
}catch(NoSuchMethodException|SecurityExceptione)
{
e.printStackTrace();
}
}}576777879808182838485868788
Constructor類中的方法的使用www.xiaoyuani.com(含代碼和注釋):
java.lang.reflect.Constructor:
Constructor[]getConstructor()獲得本類里的public許可權修飾符構造函數,不能獲取父類的!
Constructor[]getDeclaredConstructor()獲得本類中的所以構造函數!
Constructor<T>getConstructor(Class...parameterType)用參數決定獲得本類中的某個的構造方法,只能獲得public的
Constructor<T>getDeclaredConstructor(Class...parameterType)用參數決定獲得本類中的某個構造方法
附:
JDK8.0之後新增的類:
Executable:
它是Method和Constructor的父類
常用方法:
getParameter()獲得類中方法參數
getExceptionTypes()獲得類中某個方法拋出異常類型
getMoidfiers()獲得方法許可權修飾符
Parameter:
封裝並代表了參數實例123456789101112131415
packageLessonForReflection03;importjava.lang.reflect.Constructor;importjava.lang.reflect.Modifier;importjava.lang.reflect.Parameter;/*
*java.lang.reflect.Constructor
*
*Constructor[]getConstructor();獲得本類里的public許可權修飾符構造函數,不能獲取父類的
*Constructor[]getDeclaredConstructor();得本類里的全部構造
*
*Constructor<T>getConstructor(Class...parameterType);用參數決定獲得哪個構造方法
*Constructor<T>getDeclaredConstructor(Class...parameterType);
*
*/{
publicstaticvoidmain(String[]args)
{
System.out.println("獲得Cricle本類里的public許可權修飾符構造函數,不能獲取父類的Constructor[]getConstructor()");
System.out.println("子類繼承不了父類中的構造方法和private");
//Constructor[]getConstructor()獲得Cricle本類里的public許可權修飾符構造函數,不能獲取父類的
//子類繼承不了父類中的構造方法和private
Class<Circle>c1=Circle.class;
Constructor<?>[]cons1=c1.getConstructors();
for(Constructor<?>cons:cons1)
{
System.out.println(cons);
//System.out.println(cons.getName());
}
System.out.println("-----------------------");
System.out.println("方法獲得本類中的所有構造函數getDeclaredConstructor()");
Constructor<?>[]cons2=c1.getDeclaredConstructors();
for(Constructor<?>cons:cons2)
{
System.out.println(cons);
}
System.out.println("-----------------------");
try
{
System.out.println("方法用參數指定獲得本類!構造方法,只能獲取public的Constructor<T>getConstructor(Class...parameterType)");
Constructor<?>cons3=c1.getConstructor(int.class);
System.out.println(Modifier.toString(cons3.getModifiers()));
System.out.println(cons3);
System.out.println("-----------------------");
System.out.println("方法用參數指定獲得本類!構造方法任何許可權修飾符的都可以獲得Constructor<T>getDeclaredConstructor(Class...parameterType)");
Constructor<?>cons4=c1.getDeclaredConstructor(String.class);
System.out.println(cons4);
System.out.println("-----------------------");
/*
*JDK8.0之後新增的類
*Executable:
*是Method和Constructor的父類
*方法:
*getParameter();
*getExceptionTypes();
*getModifiers();
*getTypeParameters();
*
*Parameter:
*封裝並代表了參數實例
*/
System.out.println("獲取類中方法的參數getParameters()");
Constructor<?>cons5=c1.getDeclaredConstructor(int.class,String.class);
Parameter[]p1=cons5.getParameters();
for(Parameterp:p1)
{
System.out.println(p);
}
}catch(NoSuchMethodException|SecurityExceptione)
{
e.printStackTrace();
}
}}5767778798081828384858687
代碼中提到的Circle類和Shape類二者為繼承關系:
packageLessonForReflection03;publicclassCircleextendsShape{
privateintr;
privateStringcolor;
publicCircle(intr,Stringcolor)
{
super();
this.r=r;
this.color=color;
}
publicCircle(intr)
{
super();
this.r=r;
}
protectedCircle(Stringcolor)
{
super();
this.color=color;
}
Circle()
{
super();
}}
packageLessonForReflection03;publicclassShape{
privateintper;
publicShape(intper)
{
super();
this.per=per;
}
publicShape()
{
super();
}}1234567891011121314151617
部分文字來源於:
咕嘟咖啡楊海濱老師 — 《java編程語言高級特性》
輕量化研習Java相關技術倡導者
「愛碼學院」聯合創始人自適應教學理念提出者踐行者;多年開發及項目管理經歷;出版《JavaEE企業級應用與開發》一書;10餘年高校項目實踐畢設指導經驗;企業軟培經驗豐富