Java中反射的應(yīng)用
反射的應(yīng)用
1. 獲取運(yùn)行時(shí)類(lèi)的完整結(jié)構(gòu)
通過(guò)反射獲取運(yùn)行時(shí)類(lèi)的完整結(jié)構(gòu),包括一下所列都是可以獲取的,下面來(lái)試試
- Interface:實(shí)現(xiàn)的全部接口
- Superclass:所繼承的父類(lèi)
- Constructor:全部的構(gòu)造器
- Method:全部的方法
- Field:全部的屬性
- Annotation:注解
新建一個(gè) Person.java 類(lèi)
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 類(lèi),測(cè)試一下通過(guò)反射獲取上面這個(gè)類(lèi)的信息
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("==================獲取類(lèi)名=====================");
//獲取類(lèi)的名字
System.out.println("類(lèi)名:" + aClass.getSimpleName());
//獲取包名+類(lèi)名
System.out.println("包名及類(lèi)名:" + aClass.getName());
System.out.println("==================獲取類(lèi)的屬性=====================");
//獲取類(lèi)的public類(lèi)型屬性
Field[] fields1 = aClass.getFields();
for (Field field : fields1) {
System.out.println("類(lèi)的public類(lèi)型屬性:" + field);
}
//獲取類(lèi)的所有屬性
Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
System.out.println("類(lèi)的所有屬性:" + field);
}
//獲取指定的屬性
Field name = aClass.getDeclaredField("name");
System.out.println("類(lèi)的指定屬性:" + name);
System.out.println("==================獲取類(lèi)的方法=====================");
//獲取本類(lèi)及父類(lèi)的所有public類(lèi)型方法
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println("本類(lèi)及父類(lèi)的所有public類(lèi)型方法:" + method);
}
//獲取本類(lèi)及父類(lèi)的所有方法
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println("本類(lèi)父類(lèi)的所有方法:" + 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("==================獲取類(lèi)的構(gòu)造器=====================");
//獲取所有public類(lèi)型構(gòu)造器
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("獲取所有public類(lèi)型構(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ì)象
通過(guò)調(diào)用 Class 對(duì)象的 newInstance() 方法,可以創(chuàng)建類(lèi)的對(duì)象
有了類(lèi)的對(duì)象,就可以通過(guò)對(duì)象.方法名的形式使用方法了,這和平常的使用方式一樣,但需要注意設(shè)置的訪問(wèn)權(quán)限問(wèn)題
使用 Class 對(duì)象創(chuàng)建類(lèi)的對(duì)象是需要條件的,不同情況下,條件不同
使用無(wú)參構(gòu)造器時(shí)的條件
- 無(wú)參構(gòu)造器存在
- 無(wú)參構(gòu)造器的訪問(wèn)權(quán)限要足夠
//獲取Class對(duì)象
Class<?> aClass = Class.forName("com.javabasic.reflection.Person");
//通過(guò)一個(gè)無(wú)參構(gòu)造器創(chuàng)建一個(gè)Person的對(duì)象
Person person01 = (Person) aClass.newInstance();
System.out.println(person01);
使用有參構(gòu)造器時(shí)的條件
- 通過(guò) Class 類(lèi)的 getDeclaredConstructor(Class<?>… parameterTypes) 獲取當(dāng)前類(lèi)的指定有參構(gòu)造器
- 向構(gòu)造器的形參中傳遞一個(gè)對(duì)象數(shù)組進(jìn)去,里面要包含構(gòu)造器中所需的各個(gè)參數(shù)
- 通過(guò) Constructor 實(shí)例化對(duì)象
//獲取Class對(duì)象
Class<?> aClass = Class.forName("com.javabasic.reflection.Person");
//通過(guò)有參構(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 類(lèi),然后新建一個(gè)測(cè)試類(lèi)來(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");
//通過(guò)一個(gè)無(wú)參構(gòu)造器創(chuàng)建一個(gè)Person的對(duì)象
Person person01 = (Person) aClass.newInstance();
System.out.println(person01);
//通過(guò)有參構(gòu)造器創(chuàng)建對(duì)象
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, Integer.class);
Person person02 = (Person) declaredConstructor.newInstance("張三", 20);
System.out.println(person02);
//通過(guò)反射調(diào)用普通方法
Method method = aClass.getDeclaredMethod("setName", String.class);
method.setAccessible(true); //關(guān)閉安全檢測(cè),允許訪問(wèn)private方法
Person person03 = (Person) aClass.newInstance();
method.invoke(person03, "李四"); //向person03對(duì)象中的setName方法傳參
System.out.println(person03);
//通過(guò)反射調(diào)用屬性
Field field01 = aClass.getDeclaredField("name");
Field field02 = aClass.getDeclaredField("age");
field01.setAccessible(true); //關(guān)閉安全檢測(cè),允許訪問(wèn)private屬性
field02.setAccessible(true);
Person person04 = (Person) aClass.newInstance();
field01.set(person04, "王五"); //設(shè)置名字
field02.set(person04, 19); //設(shè)置年齡
System.out.println(person04);
}
}
值得注意的是,如果方法或者屬性的訪問(wèn)權(quán)限是 private,那么需要配置 .setAccessible(true);,不然無(wú)法訪問(wèn)
3. 反射操作泛型
java 采用泛型擦除的機(jī)制來(lái)引入泛型,但卻只是給編譯器 javac 使用的,用于確保數(shù)據(jù)的安全性和免去強(qiáng)制類(lèi)型轉(zhuǎn)換的問(wèn)題,而一旦編譯完成,所有與泛型相關(guān)的類(lèi)型會(huì)全部擦除
為了通過(guò)反射能操作這些類(lèi)型,java 新增了 ParameterizedType、GenericArrayType、TypeVariable、WildcardType 這幾種類(lèi)型來(lái)代表不能被歸一到 Class 類(lèi)中的類(lèi)型但又和原始類(lèi)型齊名的類(lèi)型
- ParameterizedType:表示一種參數(shù)化類(lèi)型,比如 Collection< String >
- GenericArrayType:表示一種元素類(lèi)型是參數(shù)化類(lèi)型或者類(lèi)型變量的數(shù)組類(lèi)型
- TypeVariable:各種類(lèi)型變量的公共父接口
- WildcardType :代表一種通配符類(lèi)型表達(dá)式
下面寫(xiě)一個(gè)類(lèi)來(lái)實(shí)踐一下,這里還是延用前面的 Person 類(lèi)
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ù)化類(lèi)型,即是不是前面定義的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("返回值類(lèi)型:" + 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è)使用上面的注解的類(lèi),如下:
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)記在類(lèi)上的注解")
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è)試類(lèi),測(cè)試通過(guò)反射操作注解,如下:
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");
//通過(guò)反射獲得注解
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);
//獲得類(lèi)中方法或者屬性上指定的注解
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)文章
Java class文件格式之屬性詳解_動(dòng)力節(jié)點(diǎn)java學(xué)院整理
這篇文章主要介紹了Java class文件格式之屬性詳解,需要的朋友可以參考下2017-06-06
Java 內(nèi)省(Introspector)深入理解
這篇文章主要介紹了Java 內(nèi)省(Introspector)深入理解的相關(guān)資料,需要的朋友可以參考下2017-03-03
SpringBoot為啥不用配置啟動(dòng)類(lèi)的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot為啥不用配置啟動(dòng)類(lèi)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
Spring4下validation數(shù)據(jù)校驗(yàn)無(wú)效(maven)的解決
這篇文章主要介紹了Spring4下validation數(shù)據(jù)校驗(yàn)無(wú)效(maven)的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Java調(diào)用opencv實(shí)現(xiàn)圖片矯正功能
這篇文章主要為大家詳細(xì)介紹了Java如何調(diào)用opencv實(shí)現(xiàn)圖片矯正功能,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-09-09
Spring boot詳解緩存redis實(shí)現(xiàn)定時(shí)過(guò)期方法
本篇文章分享的就是spring boot中的一個(gè)輪子,spring cache注解的方式實(shí)現(xiàn)接口數(shù)據(jù)緩存。默認(rèn)的配置想非常簡(jiǎn)單,但是有一個(gè)弊端是緩存數(shù)據(jù)為永久緩存,本次將介紹如何設(shè)置接口緩存數(shù)據(jù)的過(guò)期時(shí)間2022-07-07
Java中數(shù)組與集合的相互轉(zhuǎn)換實(shí)現(xiàn)解析
這篇文章主要介紹了Java中數(shù)組與集合的相互轉(zhuǎn)換實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
Java中JSONObject與JSONArray的使用區(qū)別詳解
這篇文章主要介紹了Java中JSONObject與JSONArray的使用區(qū)別詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11

