Java中反射詳解
閱讀目錄
- Java反射API
- 通過反射創(chuàng)建實例對象
- 通過反射調(diào)用私有方法
- 關(guān)于javap工具
- 參考資料
Java反射API
Java反射指的是在運(yùn)行狀態(tài)時,能夠獲取類的屬性和方法或者修改類運(yùn)行時行為的過程。
java.lang.Class類提供了很多方法用于獲取元數(shù)據(jù)、檢查和改變類運(yùn)行時的行為。
Java的反射主要涉及java.lang和java.lang.reflect包下的類。
反射應(yīng)用場景舉例
- IDE, 如Eclipse、MyEclipse、NetBeans等;
- 調(diào)試器;
- 測試工具等;
- 各大框架、spring、hibernate等;
java.lang.Class類
java.lang.Class主要提供了以下兩個功能:
- 提供方法用于訪問運(yùn)行期間類的元數(shù)據(jù);
- 提供方法用于檢查和修改類的運(yùn)行時行為;
java.lang.Class類常用方法
| Method | Description |
|---|---|
| 1) public String getName() | 返回類名 |
| 2) public static Class forName(String className)throws ClassNotFoundException | 加載類并返回Class對象 |
| 3) public Object newInstance()throws InstantiationException,IllegalAccessException | 創(chuàng)建實例對象 |
| 4) public boolean isInterface() | 判斷是否是接口 |
| 5) public boolean isArray() | 判斷是否是數(shù)組 |
| 6) public boolean isPrimitive() | 判斷是否是原始數(shù)據(jù)類型 |
| 7) public Class getSuperclass() | 返回父類Class引用 |
| 8) public Field[] getDeclaredFields()throws SecurityException | 返回類的成員屬性字段數(shù)組 |
| 9) public Method[] getDeclaredMethods()throws SecurityException | 返回類的方法數(shù)組 |
| 10) public Constructor[] getDeclaredConstructors()throws SecurityException | 返回類的構(gòu)造方法數(shù)組 |
| 11) public Method getDeclaredMethod(String name,Class[] parameterTypes)throws NoSuchMethodException,SecurityException | 返回類中指定參數(shù)類型的方法 |
怎樣獲取Class對象
有三種方式,如下:
- Class類的forName()方法,動態(tài)加載,運(yùn)行時,開始裝入類, 并做類的靜態(tài)初始化
- 對象的getClass()方法,靜態(tài)加載(編譯時已加載)
- .class語法, 靜態(tài)加載(編譯時已加載)
forName()方法示例
可用于動態(tài)加載,當(dāng)你知道類的全限定名時,可以使用該方式。注意原始數(shù)據(jù)類型不適用該方法;
package tmp;
class Simple
{
}
public class Test
{
public static void main(String args[]) throws ClassNotFoundException
{
Class<?> c = Class.forName("tmp.Simple");
System.out.println(c.getName());
System.out.println(c.getSimpleName());
}
}
tmp.Simple Simple
getClass()方法示例:
從實例對象中獲取Class對象
package tmp;
class Simple
{
}
public class Test
{
void printName(Object obj)
{
}
public static void main(String args[])
{
Simple s = new Simple();
Class<? extends Object> c = s.getClass();
System.out.println(c.getName());
System.out.println(c.getSimpleName());
}
}
tmp.Simple Simple
.class語法示例
作用于類名上,也可應(yīng)用于原始數(shù)據(jù)類型,如下所示:
package tmp;
public class Test
{
public static void main(String args[])
{
Class<Boolean> c = boolean.class;
System.out.println(c.getName());
Class<Test> c2 = Test.class;
System.out.println(c2.getName());
}
}
boolean tmp.Test
判斷Class對象對應(yīng)的類型
以下方法可用于判斷Class對象對應(yīng)的類型:
| 1) public boolean isInterface(): 是否對應(yīng)接口 |
| 2) public boolean isArray(): 是否對應(yīng)數(shù)組 |
| 3) public boolean isPrimitive(): 是否對應(yīng)原始數(shù)據(jù)類型 |
代碼示例:
package tmp;
class Simple
{
}
interface My
{
}
public class Test
{
public static void main(String args[])
{
try
{
Class<?> c = Class.forName("tmp.Simple");
System.out.println(c.isInterface());
Class<?> c2 = Class.forName("tmp.My");
System.out.println(c2.isInterface());
}
catch (Exception e)
{
System.out.println(e);
}
}
}
false true
通過反射創(chuàng)建實例對象
有兩種方式,如下:
- 通過Class對象的newInstance()方法創(chuàng)建,這種方式只能調(diào)用無參構(gòu)造方法;
- 通過Constructor對象的newInstance()方法創(chuàng)建,這種方式適用于有參構(gòu)造方法,并且還可以破壞單例模式,調(diào)用私有構(gòu)造方法;
所以,通常來講,第二種方式比第一種使用范圍更廣。
Class對象調(diào)用newInstance()方法示例
package tmp;
class Simple
{
void message()
{
System.out.println("Hello Java");
}
}
public class Test
{
public static void main(String args[])
{
try
{
Class<?> c = Class.forName("tmp.Simple");
Simple s = (Simple) c.newInstance();
s.message();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
Hello Java
Constructor對象調(diào)用newInstance()方法示例
注意這里可以根據(jù)傳入?yún)?shù)的類型來得到指定的構(gòu)造方法,還可以改變構(gòu)造方法的訪問權(quán)限限制。
package tmp;
import java.lang.reflect.Constructor;
class Simple
{
private String msg;
void message()
{
System.out.println("Hello Java," + msg);
}
private Simple(String s){
this.msg = s;
}
}
public class Test
{
public static void main(String args[])
{
try
{
Class<?> c = Class.forName("tmp.Simple");
Constructor<?> con = c.getDeclaredConstructor(String.class);
con.setAccessible(true);
Simple s = (Simple) con.newInstance("...");
s.message();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
Hello Java,...
通過反射調(diào)用私有方法
通過反射,我們可以調(diào)用其它類的私有方法,主要涉及java.lang.Class和java.lang.reflect.Method類;
其中主要是用到了Method類的setAccessible方法和invoke方法,前者修改訪問權(quán)限,后者調(diào)用方法。
通過調(diào)用有參私有方法示例:
package tmp;
import java.lang.reflect.Method;
class A
{
private void cube(int n)
{
System.out.println(n * n * n);
}
}
class Test
{
public static void main(String args[]) throws Exception
{
Class<A> c = A.class;
Object obj = c.newInstance();
Method m = c.getDeclaredMethod("cube", new Class[]{ int.class });
m.setAccessible(true);
m.invoke(obj, 4);
}
}
關(guān)于javap工具
使用javap命令可以反匯編java的字節(jié)碼文件,展示class文件中的字段屬性、構(gòu)造方法、普通方法信息;
使用說明:

javap java.lang.Object示例
javap -c Test示例:

寫個簡單的Test類,如下:
package tmp;
class Simple
{
}
public class Test
{
public static void main(String args[])
{
System.out.println("Hello");
}
}
輸入javap -c Test:

參考資料
基本屬于翻譯,做了小部分修改
http://www.javatpoint.com/java-reflection
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!
相關(guān)文章
java多態(tài)性中的Overload和Override區(qū)別詳解
這篇文章主要介紹了java多態(tài)性中的Overload和Override區(qū)別詳解,重寫(Overriding)是父類與子類之間多態(tài)性的一種表現(xiàn),而重載(Overloading)是一個類中多態(tài)性的一種表現(xiàn),需要的朋友可以參考下2023-07-07
Flink結(jié)合Kafka實現(xiàn)通用流式數(shù)據(jù)處理
這篇文章將和大家一起深入探討Flink和Kafka的關(guān)系以及它們在數(shù)據(jù)流處理中的應(yīng)用,并提供一些最佳實踐和實際案例,希望對大家有一定的幫助2025-03-03
Java 高并發(fā)十: JDK8對并發(fā)的新支持詳解
本文主要介紹Java 高并發(fā)JDK8的支持,這里整理了詳細(xì)的資料及1. LongAdder 2. CompletableFuture 3. StampedLock的介紹,有興趣的小伙伴可以參考下2016-09-09
一文帶你掌握J(rèn)ava?LinkedBlockingQueue
LinkedBlockingQueue?是一個可選有界阻塞隊列,這篇文章主要為大家詳細(xì)介紹了Java中LinkedBlockingQueue的實現(xiàn)原理與適用場景,感興趣的可以了解一下2023-04-04
Spring定時任務(wù)中@PostConstruct被多次執(zhí)行異常的分析與解決
這篇文章主要給大家介紹了關(guān)于Spring定時任務(wù)中@PostConstruct被多次執(zhí)行異常的分析與解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10

