Java類反射(能力更上一臺階,Java跳躍)
如果你屬於初級學習者,當你看類反射之後,說明你的程式設計能力又升級了!
什麼是類反射:
JAVA反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為Java語言的反射機制。
反射(Reflection)是Java程式開發語言的特徵之一,它允許執行中的Java程式對自身進行檢查, 也稱自審,並能直接操作程式的內部屬性。例如,使用它能獲得Java類中各成員的名稱並顯示出來。
Java的這一能力在實際應用中應用得很多,在其它的程式語言中根本就不存在這一牲。例如,Pascal、C或者C++中就沒有辦法在程式中獲得函式定義相關的資訊。
JavaBean是類反射的實際應用之一,它能讓一些工具視覺化的操作軟體元件。這些工具通過類反射動態的載入並取得Java元件(類)的屬性。後面學習的各種框架,基本上都會有反射的使用。
首先舉個例子:
api
<span style="font-size:18px;">/**
*
*/
package cn.hncu.reflect.test1.api;
/**
* @author xinxin
*
*/
public interface Intfaceebo {
public void work();
}</span>
UsbFactory
<span style="font-size:18px;">/**
*
*/
package cn.hncu.reflect.test1.Factory;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import cn.hncu.reflect.test1.api.Intfaceebo;
import cn.hncu.reflect.test1.imp.Imp;
/**
* @author xinxin
*
*/
public class USbFatory {
public static Intfaceebo getUsb(){
// S<span style="color:#000099;">tring name1 ="cn.hncu.reflect.test1.imp.Imp";
// String name2 ="cn.hncu.reflect.test1.imp.Imp2";</span>
try {
// 通過修改 name 就可以呼叫不同的類,實現了 解耦
//name 不需要依靠類了,只需要路徑名就可以獲得該類的所有資訊
<span style="color:#ff0000;">//此處手動改麻煩,還可以 過修改屬性檔案(這樣寫就比較大了,當然修改屬性可以用介面,讓使用者自己進行修噶</span>)
Properties p =new Properties();
File file =new File("properties.cog");
if(!file.exists()){
file.createNewFile();
}
FileInputStream files =new FileInputStream(file);//配置檔案需要 IO流
p.load(files);//讀檔案中的資料
<span style="color:#ff0000;">String name = p.getProperty("name").trim();//從配置檔案中取出來
Class clazz=Class.forName(name);//字串傳過來的 進行類反射
Intfaceebo c=(Intfaceebo) clazz.newInstance();//獲得類反射之後的物件</span>
return c;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
//1,
//String name1 ="cn.hncu.reflect.test1.imp.Imp";
//(當Class clazz=Class.forName(name1);)work1 is Working
// USbFatory.getUsb().work();//執行結果 work1 is Working
// 2,String name2 ="cn.hncu.reflect.test1.imp.Imp2";
//Class clazz=Class.forName(name2);
// USbFatory.getUsb().work();// work2 is Working
// 採用配置檔案寫之後
USbFatory.getUsb().work();
//name =cn.hncu.reflect.test1.imp.Imp //work1 is Working
// name =cn.hncu.reflect.test1.imp.Imp2 //work2 is Working
}
}
</span>
imp包
<span style="font-size:18px;">/**
*
*/
package cn.hncu.reflect.test1.imp;
import cn.hncu.reflect.test1.api.Intfaceebo;
/**
* @author xinxin
*
*/
public class Imp implements Intfaceebo {
public void work() {
System.out.println("work1 is Working");
}
}
</span>
imp2
<span style="font-size:18px;">/**
*
*/
package cn.hncu.reflect.test1.imp;
import cn.hncu.reflect.test1.api.Intfaceebo;
/**
* @author xinxin
*
*/
public class Imp2 implements Intfaceebo {
public void work() {
System.out.println("work2 is Working");//僅僅只是測試使用
}
}</span>
這幾個類中,factory中用到了類反射,可以根據Class.forName("name")來獲得相對應的Class 物件,相關的測試以及測試的結果都在後面的註釋裡,main函式為了方便寫到了factory裡面。
反射使用的三個步驟 :
如:method
第一步:獲得你想操作的類的java.lang.Class物件。在執行中的Java程式中,用java.lang.Class類來描述類和介面等。
第二步:呼叫諸如getDeclaredMethods的方法,取得該類中定義的所有方法的列表。
第三步:使用反射的API來操作這些資訊。
自己寫的Instance 測試類
1,首先需要一個物件
/**
*
*/
package cn.hncu.reflect.test;
/**
* @author xinxin
*
*/
public class A {
}
,2,進行判斷(也就是呼叫Class.isInstance(),執行是都匹配)
/**
*
*/
package cn.hncu.reflect.test;
/**
* @author xinxin
*
*/
public class TestInstanceof {
/**
* @param args
*/
/*
* 驗證 instanceof 功能 通過這個函式isInstanceof
* 通過類反射Class 中的isInstance 判斷下
*/
public static void main(String[] args) {
<span style="color:#ff0000;">System.out.println( isInstanceof(new A()));//結果 true
System.out.println( isInstanceof(new Integer(10)));// false</span>
}
private static boolean isInstanceof( Object obj) {
boolean isT=false;
try {
<span style="color:#ff9900;">Class c =Class.forName("cn.hncu.reflect.test.A");//通過傳過來的字串,獲得Class型別
isT=c.isInstance(obj);</span>
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return isT;
}
}
獲取Class物件的三種方式:
1,通過物件的getClass方法進行獲取。這種方式需要具體的類和該類的物件,以及呼叫getClass方法。
2, 任何資料型別(包括基本資料型別)都具備著一個靜態的屬性class,通過它可直接獲取到該型別對應的Class物件。這種方式要使用具體的類,然後呼叫類中的靜態屬性class完成,無需呼叫方法,效能更好。
3,通過Class.forName()方法獲取。這種方式僅需使用類名,就可以獲取該類的Class物件,更有利於擴充套件。
例項演示:
/**
*
*/
package cn.hncu.reflect.Three;
import java.lang.reflect.Method;
/**
* @author xinxin
*
*/
public class ReflectThree {
/**
* @param args
*/
//類反射必須先有類,匯入Person
//這僅僅是獲得Class 物件
public static void main(String[] args) {
// getObject1();//通過物件的getClass方法進行獲取。
//、這種方式需要具體的類和該類的物件,以及呼叫getClass方法。
//2,任何資料型別(包括基本資料型別)都具備著一個靜態的屬性class,
// 通過它可直接獲取到該型別對應的Class物件。這種方式要使用具體的類,
// 然後呼叫類中的靜態屬性class完成,無需呼叫方法,效能更好。
// getObject2();
//3,通過Class.forName()方法獲取。這種方式僅需使用類名,
// 就可以獲取該類的Class物件,更有利於擴充套件。、
// getObject3();
//4 小小的先實驗一下 獲得類反射出的方法
getMethod();
}
<span style="color:#ff0000;">//1,已知具體的類 </span>
private static void getObject1() {
Person p =new Person("jack", 11);
Class c =<span style="color:#ff0000;">p.getClass()</span>;//獲得Class 物件
System.out.println(c);//class cn.hncu.reflect.Three.Person
}
//任何物件包括基本資料型別都有.class 獲得Class 物件
private static void getObject2() {
Class c =<span style="color:#ff0000;">String.class</span>;
System.out.println(c);//class java.lang.String
}
/*
<span style="color:#ff0000;">* 通過Class.forName(str)的方式獲取Class物件,
* 該方式依賴的是字串(類的名字),可以實現解耦</span>
*/
private static void getObject3() {
String name ="cn.hncu.reflect.Three.Person";
try {
<span style="color:#ff0000;">Class c =Class.forName(name)</span>;
System.out.println(c);//class cn.hncu.reflect.Three.Person
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private static void getMethod() {
String name ="cn.hncu.reflect.Three.Person";
try {
Class c =Class.forName(name);
// Object obj=c.newInstance();// 建立此 Class 物件所表示的類的一個新例項。
Method method[] =c.getMethods();//獲得包括本身,父類的所有public方法
// Method method[] =c.getDeclaredMethods();//獲得當前類的所有方法包括 private 等
for(int i=0;i<method.length;i++){
System.out.println(method[i]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
前面的基礎基本介紹完了,現在開始解刨得到類物件之後:
獲取類的方法:找出一個類中定義了些什麼方法,這是一個非常有價值也非常基礎的反射用法。
程式碼演示:首先需要一個未知的類(USerModel*(在做書店管理系統時用到的,直接拷貝過來)*)
/**
*
*/
package cn.hncu.reflect.reflectDecompose;
import java.io.Serializable;
public class UserModel{
private String uuid;
private String name;
private static int type;
private String pwd;
public UserModel(String uuid, String name, int type, String pwd) {
super();
this.uuid = uuid;
this.name = name;
this.type = type;
this.pwd = pwd;
}
public UserModel(String uuid, int type){
this.uuid = uuid;
this.type = type;
}
public UserModel(){
}
private UserModel(String uuid){
this.uuid = uuid;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String toString() {
return "{"+uuid+","+name+","+type+","+pwd+"}";
}
private long privateMethod( double a){
return (long)a;
}
void defaultMethod(int i){
System.out.println("aa");
}
}
然後就是我們的測試類:
獲取類的方法:
private static void fetchMehtod(String name) throws Exception{
Class c=Class.forName(name);
Method method[] =c.getMethods();
for(int i=0;i<method.length;i++){
//方法名
Method m =method[i];
System.out.println("name:"+m.getName());
System.out.println(m.getDeclaringClass());
//getDeclaringClass(),,如果此 Class 物件所表示的類或介面是另一個類的成員,則返回的 Class 物件表示該物件的宣告類。
// 獲得方法出現的異常
Class[] ex= m.getExceptionTypes();
for(int j=0;j<ex.length;j++){
System.out.println("exception:"+ex[j]);
}
//引數型別
Class par[]=m.getParameterTypes();
for(int j=0;j<par.length;j++){
System.out.println("Parameter:"+par[j]);
}
System.out.println("type:"+m.getReturnType());
}
}
獲取類的構造器:找出一個類中定義的構造方法,構造器沒有返回型別
/**
* 獲取類中建構函式的資訊
* getConstructors() : 獲取當前類的public構造方法
* getDeclaredConstructors() :獲取當前類宣告的所有構造方法,包括private等其它非public方法
*/
private static void fetchConstror(String name2) throws Exception {
Class c=Class.forName(name);
// Constructor[] con= c.getConstructors();
Constructor[] con= c.getDeclaredConstructors();
for(int i=0;i<con.length;i++){
//方法名
Constructor cons=con[i];
System.out.println("name:"+cons.getName());
System.out.println("DeclaringClass"+cons.getDeclaringClass());
//getDeclaringClass(),,如果此 Class 物件所表示的類或介面是另一個類的成員,則返回的 Class 物件表示該物件的宣告類。
// 獲得方法出現的異常
Class[] ex= cons.getExceptionTypes();
for(int j=0;j<ex.length;j++){
System.out.println("exception:"+ex[j]);
}
//引數型別
Class par[]=cons.getParameterTypes();
for(int j=0;j<par.length;j++){
System.out.println("Parameter:"+par[j]);
}
}
}
獲取類的屬性欄位:找出一個類中定義了哪些屬性欄位。
private static void fetField(String name) throws Exception{
Class c=Class.forName(name);
// Field field[]=c.getFields();//只能訪問 public許可權
Field field[]=c.getDeclaredFields();//獲取當前類宣告的所有構造方法,包括private等其它非public變數
for(int i=0;i<field.length;i++){
Field f=field[i];
System.out.println("name:"+f.getName());//變數名
System.out.println("Declaring:"+f.getDeclaringClass());//該類的明細路徑
System.out.println("type:"+f.getType());// 變數的型別
int mod =f.getModifiers();
System.out.println("Modifiers::"+f);//變數的修飾符
System.out.println("Modifiers::"+Modifier.toString(mod));//輸出型別 如 public private
}
一起到這裡我們已經會從獲得的類中得到未知類的資訊了,後面會有持續更新。
相關文章
- java反射之Class類Java反射
- 反射+Class類方法_利用反射分析類的能力反射
- 【轉】跳躍表-原理及Java實現Java
- Java jvm 類載入 反射JavaJVM反射
- java反射—— 對類的分析Java反射
- Java類反射再次升級Java反射
- java進階(41)--反射機制Java反射
- Java高階語法之反射Java反射
- Java中的類反射機制Java反射
- 為你的 Python 平臺類遊戲新增跳躍功能Python遊戲
- java反射學習(一)Java反射
- Java列舉類、註解和反射Java反射
- 平臺跳躍試驗小品《Himno》免費上架中
- JAVA的反射機制==>用反射分析類的實現Java反射
- java反射——反射AnnotationJava反射
- 【Java 反射學習】Java 反射基礎Java反射
- [Java 反射學習] Java 反射基礎Java反射
- 探索JAVA系列(一)探祕Java反射(Reflect)Java反射
- 【Java】跳躍表的實現以及用例測試Java
- Java 反射Java反射
- Java——反射Java反射
- Java反射Java反射
- 深入理解Java反射(一)Java反射
- 淺析Java反射--JavaJava反射
- Java進階 | 泛型機制與反射原理Java泛型反射
- Java 反射由淺入深 | 進階必備Java反射
- Java高階特性之反射學習總結Java反射
- 菜鳥學Java(十四)——Java反射機制(一)Java反射
- 【Redis】跳躍表原理分析與基本程式碼實現(java)RedisJava
- leetcode:跳躍遊戲II(java貪心演算法)LeetCode遊戲Java演算法
- Java筆記-反射機制(一)Java筆記反射
- 一篇瞭解Java反射Java反射
- java反射呼叫set和get方法的通用類Java反射
- Java反射獲取類和物件資訊全解析Java反射物件
- Java 反射原理Java反射
- Java反射-模組Java反射
- Java的反射Java反射
- java反射——FieldJava反射