Java中反射的應(yīng)用
反射的應(yīng)用
1. 獲取運(yùn)行時(shí)類的完整結(jié)構(gòu)
通過反射獲取運(yùn)行時(shí)類的完整結(jié)構(gòu),包括一下所列都是可以獲取的,下面來(lái)試試
- Interface:實(shí)現(xiàn)的全部接口
- Superclass:所繼承的父類
- Constructor:全部的構(gòu)造器
- Method:全部的方法
- Field:全部的屬性
- Annotation:注解
新建一個(gè) Person.java 類
package com.javabasic.reflection;
/**
* @Description
* @ClassName Person
* @Author yuhuofei
* @Date 2022/9/25 16:44
* @Version 1.0
*/
public class Person {
private String name;
private Integer age;
private String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
private Integer getAge() {
return age;
}
private void setAge(Integer age) {
this.age = age;
}
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
新建 TestReflection.java 類,測(cè)試一下通過反射獲取上面這個(gè)類的信息
package com.javabasic.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @Description 反射的應(yīng)用
* @ClassName TestReflection
* @Author yuhuofei
* @Date 2022/10/2 15:57
* @Version 1.0
*/
public class TestReflection {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class<?> aClass = Class.forName("com.javabasic.reflection.Person");
System.out.println("==================獲取類名=====================");
//獲取類的名字
System.out.println("類名:" + aClass.getSimpleName());
//獲取包名+類名
System.out.println("包名及類名:" + aClass.getName());
System.out.println("==================獲取類的屬性=====================");
//獲取類的public類型屬性
Field[] fields1 = aClass.getFields();
for (Field field : fields1) {
System.out.println("類的public類型屬性:" + field);
}
//獲取類的所有屬性
Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
System.out.println("類的所有屬性:" + field);
}
//獲取指定的屬性
Field name = aClass.getDeclaredField("name");
System.out.println("類的指定屬性:" + name);
System.out.println("==================獲取類的方法=====================");
//獲取本類及父類的所有public類型方法
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println("本類及父類的所有public類型方法:" + method);
}
//獲取本類及父類的所有方法
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println("本類父類的所有方法:" + method);
}
//獲取指定方法
Method getName = aClass.getDeclaredMethod("getName", null);
Method setName = aClass.getDeclaredMethod("setName", String.class);
System.out.println("獲取指定的getName方法:" + getName);
System.out.println("獲取指定的setName方法:" + setName);
System.out.println("==================獲取類的構(gòu)造器=====================");
//獲取所有public類型構(gòu)造器
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("獲取所有public類型構(gòu)造器:" + constructor);
}
//獲取所有構(gòu)造器
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
for (Constructor constructor : declaredConstructors) {
System.out.println("獲取所有構(gòu)造器:" + constructor);
}
//獲取指定的構(gòu)造器
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, Integer.class);
System.out.println("獲取指定的構(gòu)造器:" + declaredConstructor);
}
}
結(jié)果如下

2. 動(dòng)態(tài)創(chuàng)建對(duì)象動(dòng)態(tài)操作方法及屬性
2.1 動(dòng)態(tài)創(chuàng)建對(duì)象
通過調(diào)用 Class 對(duì)象的 newInstance() 方法,可以創(chuàng)建類的對(duì)象
有了類的對(duì)象,就可以通過對(duì)象.方法名的形式使用方法了,這和平常的使用方式一樣,但需要注意設(shè)置的訪問權(quán)限問題
使用 Class 對(duì)象創(chuàng)建類的對(duì)象是需要條件的,不同情況下,條件不同
使用無(wú)參構(gòu)造器時(shí)的條件
- 無(wú)參構(gòu)造器存在
- 無(wú)參構(gòu)造器的訪問權(quán)限要足夠
//獲取Class對(duì)象
Class<?> aClass = Class.forName("com.javabasic.reflection.Person");
//通過一個(gè)無(wú)參構(gòu)造器創(chuàng)建一個(gè)Person的對(duì)象
Person person01 = (Person) aClass.newInstance();
System.out.println(person01);
使用有參構(gòu)造器時(shí)的條件
- 通過 Class 類的 getDeclaredConstructor(Class<?>… parameterTypes) 獲取當(dāng)前類的指定有參構(gòu)造器
- 向構(gòu)造器的形參中傳遞一個(gè)對(duì)象數(shù)組進(jìn)去,里面要包含構(gòu)造器中所需的各個(gè)參數(shù)
- 通過 Constructor 實(shí)例化對(duì)象
//獲取Class對(duì)象
Class<?> aClass = Class.forName("com.javabasic.reflection.Person");
//通過有參構(gòu)造器創(chuàng)建對(duì)象
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, Integer.class);
Person person02 = (Person) declaredConstructor.newInstance("張三", 20);
System.out.println(person02);
2.2 動(dòng)態(tài)操作方法及屬性
這里延用上面的 Person.java 類,然后新建一個(gè)測(cè)試類來(lái)測(cè)試
package com.javabasic.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @Description
* @ClassName Test01
* @Author yuhuofei
* @Date 2022/10/2 17:08
* @Version 1.0
*/
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//獲取Class對(duì)象
Class<?> aClass = Class.forName("com.javabasic.reflection.Person");
//通過一個(gè)無(wú)參構(gòu)造器創(chuàng)建一個(gè)Person的對(duì)象
Person person01 = (Person) aClass.newInstance();
System.out.println(person01);
//通過有參構(gòu)造器創(chuàng)建對(duì)象
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, Integer.class);
Person person02 = (Person) declaredConstructor.newInstance("張三", 20);
System.out.println(person02);
//通過反射調(diào)用普通方法
Method method = aClass.getDeclaredMethod("setName", String.class);
method.setAccessible(true); //關(guān)閉安全檢測(cè),允許訪問private方法
Person person03 = (Person) aClass.newInstance();
method.invoke(person03, "李四"); //向person03對(duì)象中的setName方法傳參
System.out.println(person03);
//通過反射調(diào)用屬性
Field field01 = aClass.getDeclaredField("name");
Field field02 = aClass.getDeclaredField("age");
field01.setAccessible(true); //關(guān)閉安全檢測(cè),允許訪問private屬性
field02.setAccessible(true);
Person person04 = (Person) aClass.newInstance();
field01.set(person04, "王五"); //設(shè)置名字
field02.set(person04, 19); //設(shè)置年齡
System.out.println(person04);
}
}
值得注意的是,如果方法或者屬性的訪問權(quán)限是 private,那么需要配置 .setAccessible(true);,不然無(wú)法訪問
3. 反射操作泛型
java 采用泛型擦除的機(jī)制來(lái)引入泛型,但卻只是給編譯器 javac 使用的,用于確保數(shù)據(jù)的安全性和免去強(qiáng)制類型轉(zhuǎn)換的問題,而一旦編譯完成,所有與泛型相關(guān)的類型會(huì)全部擦除
為了通過反射能操作這些類型,java 新增了 ParameterizedType、GenericArrayType、TypeVariable、WildcardType 這幾種類型來(lái)代表不能被歸一到 Class 類中的類型但又和原始類型齊名的類型
- ParameterizedType:表示一種參數(shù)化類型,比如 Collection< String >
- GenericArrayType:表示一種元素類型是參數(shù)化類型或者類型變量的數(shù)組類型
- TypeVariable:各種類型變量的公共父接口
- WildcardType :代表一種通配符類型表達(dá)式
下面寫一個(gè)類來(lái)實(shí)踐一下,這里還是延用前面的 Person 類
package com.javabasic.reflection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
/**
* @Description 測(cè)試反射獲取泛型
* @ClassName Test02
* @Author yuhuofei
* @Date 2022/10/2 20:06
* @Version 1.0
*/
public class Test02 {
public void getData(Map<String, Person> map, List<Person> list) {
System.out.println("getData()");
}
public Map<String, Person> getMap() {
System.out.println("getMap()");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
//獲取入?yún)⒎盒?
Method method = Test02.class.getMethod("getData", Map.class, List.class);
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("泛型:" + genericParameterType);
//判斷拿到的是不是參數(shù)化類型,即是不是前面定義的Map或者List
if (genericParameterType instanceof ParameterizedType) {
//獲取真實(shí)參數(shù)
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
System.out.println("============分割線===========");
//獲取返回值泛型
method = Test02.class.getMethod("getMap", null);
Type genericReturnType = method.getGenericReturnType();
System.out.println("返回值類型:" + genericReturnType);
if (genericReturnType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type at : actualTypeArguments) {
System.out.println(at);
}
}
}
}
得到的結(jié)果如下:

4. 反射操作注解
定義一個(gè)注解,如下:
package com.javabasic.annotation;
import java.lang.annotation.*;
/**
* @Description 自定義注解
* @InterfaceName MyAnnotation
* @Author yuhuofei
* @Date 2022/9/18 11:26
* @Version 1.0
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
/**
* 描述信息
*/
String value() default "";
}
定義一個(gè)使用上面的注解的類,如下:
package com.javabasic.annotation;
/**
* @Description 測(cè)試自定義注解的使用
* @ClassName TestAnnotation
* @Author yuhuofei
* @Date 2022/9/18 11:32
* @Version 1.0
*/
@MyAnnotation(value = "打印出兩個(gè)整數(shù)之和,這是標(biāo)記在類上的注解")
public class TestAnnotation {
@MyAnnotation(value = "打印出兩個(gè)整數(shù)之和,這是標(biāo)記在方法上的注解")
public static void printResult() {
int a = 39;
int b = 54;
int result = a + b;
System.out.println(result);
}
public static void main(String[] args) {
printResult();
}
}
定義一個(gè)測(cè)試類,測(cè)試通過反射操作注解,如下:
package com.javabasic.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
* @Description 測(cè)試反射獲得注解
* @ClassName Test03
* @Author yuhuofei
* @Date 2022/10/2 20:36
* @Version 1.0
*/
public class Test03 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class c = Class.forName("com.javabasic.annotation.TestAnnotation");
//通過反射獲得注解
Annotation[] annotations = c.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//獲得注解的value
MyAnnotation annotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
String value = annotation.value();
System.out.println(value);
//獲得類中方法或者屬性上指定的注解
System.out.println("============分割線===========");
Method method = c.getMethod("printResult", null);
MyAnnotation an = method.getAnnotation(MyAnnotation.class);
System.out.println(an);
System.out.println(an.value());
}
}
運(yùn)行結(jié)果:

到此這篇關(guān)于Java中反射的應(yīng)用的文章就介紹到這了,更多相關(guān)Java反射內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringCloud使用Feign實(shí)現(xiàn)遠(yuǎn)程調(diào)用流程詳細(xì)介紹
OpenFeign源于Netflix的Feign,是http通信的客戶端。屏蔽了網(wǎng)絡(luò)通信的細(xì)節(jié),直接面向接口的方式開發(fā),讓開發(fā)者感知不到網(wǎng)絡(luò)通信細(xì)節(jié)。所有遠(yuǎn)程調(diào)用,都像調(diào)用本地方法一樣完成2023-02-02
SpringBoot事件監(jiān)聽器@EventListener的實(shí)現(xiàn)
@EventListener注解用于處理應(yīng)用程序事件,提供了一種方便的方式來(lái)監(jiān)聽和響應(yīng)各種事件,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-11-11
Java實(shí)現(xiàn)U盤的插入和移除檢測(cè)程序
在現(xiàn)代計(jì)算機(jī)系統(tǒng)中,U盤的使用非常普遍,那么如何在Java程序中實(shí)現(xiàn)對(duì)U盤的插入和移除進(jìn)行檢測(cè),并對(duì)U盤中的文件進(jìn)行遞歸處理呢,下面我們就來(lái)簡(jiǎn)單介紹一下吧2025-12-12
maven-maven使用-P參數(shù)打包不同環(huán)境問題
這篇文章主要介紹了maven-maven使用-P參數(shù)打包不同環(huán)境問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
JAVA使用動(dòng)態(tài)代理對(duì)象進(jìn)行敏感字過濾代碼實(shí)例
這篇文章主要介紹了JAVA使用動(dòng)態(tài)代理對(duì)象進(jìn)行敏感字過濾代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09

