反射的使用
通過反射查看類信息
- 類的構(gòu)造方法:Class類提供了用于獲取某個類的構(gòu)造方法荒勇。
Constructor getConstructor(Class<?>... parameterTypes) 根據(jù)構(gòu)造函數(shù)的參數(shù)划鸽,返回一個具體的具有public屬性的構(gòu)造函數(shù)
Constructor getConstructors() 返回所有具有public屬性的構(gòu)造函數(shù)數(shù)組
Constructor getDeclaredConstructor(Class<?>... parameterTypes) 根據(jù)構(gòu)造函數(shù)的參數(shù)塞俱,返回一個具體的構(gòu)造函數(shù)(不分public和非public屬性)
Constructor getDeclaredConstructors() 返回該類中所有的構(gòu)造函數(shù)數(shù)組(不分public和非public屬性)
- 類的屬性:Class類提供了獲取成員屬性的方法
Field getField(String name) 根據(jù)變量名限府,返回一個具體的具有public屬性的成員變量
Field[] getFields() 返回具有public屬性的成員變量的數(shù)組
Field getDeclaredField(String name) 根據(jù)變量名,返回一個成員變量(不分public和非public屬性)
Field[] getDelcaredFields() 返回所有成員變量組成的數(shù)組(不分public和非public屬性)
- 類的方法:Class類提供了獲取成員方法的方法
Method getMethod(String name, Class<?>... parameterTypes) 根據(jù)方法名和參數(shù)灿渴,返回一個具體的具有public屬性的方法
Method[] getMethods() 返回所有具有public屬性的方法數(shù)組
Method getDeclaredMethod(String name, Class<?>... parameterTypes) 根據(jù)方法名和參數(shù)矗积,返回一個具體的方法(不分public和非public屬性)
Method[] getDeclaredMethods() 返回該類中的所有的方法數(shù)組(不分public和非public屬性)
通過反射生成并操作對象代碼實(shí)例:
package com.wechat.management.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestRefFieldAndMethod {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.wechat.management.reflection.UserDTO");
//1、獲得類的名字--->獲得包名+類名
System.out.println(c1.getName());//com.wechat.management.reflection.UserDTO
//2奶栖、獲得類的簡單名字-->獲得類名
System.out.println(c1.getSimpleName());//User
System.out.println("=======================");
//3匹表、獲得類的屬性
//3.1 獲得public的屬性
Field[] fields = c1.getFields();//只能找到public的屬性
//3.2 能夠找到所有的屬性
Field[] fields1 = c1.getDeclaredFields();
for (Field field: fields1) {
System.out.println(field);
}
/**
* private int com.wechat.management.reflection.UserDTO.id
* private java.lang.String com.wechat.management.reflection.UserDTO.name
* private int com.wechat.management.reflection.UserDTO.age
*/
//3.3门坷、獲得指定的屬性
Field name = c1.getDeclaredField("name");
System.out.println(name);//private java.lang.String com.wechat.management.reflection.UserDTO.name
//4宣鄙、獲得類的方法
System.out.println("====================================");
Method[] methods = c1.getMethods();//獲得本類及其父類的全部public方法
for (Method method : methods) {
System.out.println("c1.getMethods():"+method);
}
Method[] methods1 = c1.getDeclaredMethods();//獲得本類的全部方法
for (Method method : methods1) {
System.out.println("c1.getDeclaredMethods():"+method);
}
//獲取指定的方法 重載,所以要添加參數(shù)
Method getName = c1.getMethod("getName", null);
System.out.println(getName);//public java.lang.String com.wechat.management.reflection.UserDTO.getName()
Method setName = c1.getMethod("setName", String.class);
System.out.println(setName);//public void com.wechat.management.reflection.UserDTO.setName(java.lang.String)
//5默蚌、獲取指定的構(gòu)造器
System.out.println("=================================");
Constructor[] constructors = c1.getConstructors();//獲取public
for (Constructor constructor : constructors) {
System.out.println("c1.getConstructors():"+constructor);
}
Constructor[] constructors1 = c1.getDeclaredConstructors();//獲取所有的構(gòu)造器
for (Constructor constructor : constructors1) {
System.out.println("c1.getDeclaredConstructors():"+constructor);
}
//獲取指定的構(gòu)造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println("獲取指定的構(gòu)造器"+declaredConstructor);//獲取指定的構(gòu)造器public com.wechat.management.reflection.UserDTO(int,java.lang.String,int)
}
}
class UserDTO {
private int id;
private String name;
private int age;
public UserDTO() {
}
public UserDTO(String name, int id, int age) {
super();
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", id=" + id + ", age=" + age + "]";
}
}
通過反射調(diào)用對象方法
public class TestInvoke {
public String invokeMethod() {
System.out.println("invokeMethod已執(zhí)行冻晤!");
return "invokeMethod已執(zhí)行!";
}
public static void main(String[] args) throws Exception {
//1.通過反射獲取Class對象
Class stuClass = Class.forName("com.wechat.management.reflection.TestInvoke");//"com.wechat.management.reflection.TestInvoke"
//2.獲取invokeMethod()方法
Method method = stuClass.getMethod("invokeMethod");
//3.創(chuàng)建對象
TestInvoke testInvoke = (TestInvoke) stuClass.newInstance();
//4.調(diào)用invokeMethod()方法
String retrunStr = (String) method.invoke(testInvoke, null);
System.out.println("獲取方法執(zhí)行后的返回值:"+retrunStr);
}
}
通過反射執(zhí)行類方法的步驟:
- 通過反射獲取Class對象
- 通過getMethod()指定方法名獲取方法
- 通過反射獲取的Class類創(chuàng)建實(shí)例對象
- 通過invoke()執(zhí)行指定方法
反射與泛型
Java采用泛型擦除的機(jī)制來引入泛型绸吸,Java中的泛型僅僅是給編譯器javac使用的鼻弧,確保數(shù)據(jù)的安全性和免去強(qiáng)制類型轉(zhuǎn)換的問題,但是锦茁,一旦編譯完成攘轩,所有和泛型有關(guān)的類型全部擦除。
通過反射越過泛型檢查:
import java.lang.reflect.Method;
import java.util.ArrayList;
public class InvokeDemo {
public static void main(String[] args) throws Exception {
ArrayList<Integer> strList = new ArrayList<>();
strList.add(100);
strList.add(200);
//獲取ArrayList的Class對象码俩,反向的調(diào)用add()方法度帮,添加數(shù)據(jù)
Class listClass = strList.getClass(); //得到 strList 對象的字節(jié)碼 對象
//獲取add()方法
Method method = listClass.getMethod("add", Object.class);
//調(diào)用add()方法
method.invoke(strList, "數(shù)字");
//遍歷集合
for (Object obj : strList) {
System.out.println(obj);
}
}
}
執(zhí)行結(jié)果:
100
200
數(shù)字
為了通過反射操作泛型代表的類型,Java新增了ParameterizedType
稿存,GenericArrayType
笨篷,TypeVariable
和WildcardType
幾種類型來代表不能被歸一到Class類中的類型但是又和原始類型齊名的類型。
類型 | 說明 |
---|---|
ParameterizedType | 表示一種參數(shù)化類型瓣履,比如Collection< String > |
GenericArrayType | 表示一種元素類型是參數(shù)化類型或者類型變量的數(shù)組類型 |
TypeVariable | 是各種類型變量的公共父接口 |
WildcardType | 代表一種通配符類型表達(dá)式 |
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class TestReflectGen {
/**
* 通過泛型傳參
* @param map
* @param list
*/
public void test01(Map<String,User> map, List<Integer> list){
System.out.println("test01");
}
/**
* 通過泛型返回值
* @return
*/
public Map<String,User> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
//獲得參數(shù)類型
Method method = Test11.class.getMethod("test01", Map.class, List.class);
//獲取參數(shù)類型 即Map和 List
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("1:"+genericParameterType);
//判斷genericParameterType參數(shù)類型 是否屬于 ParameterizedType 參數(shù)化類型
if (genericParameterType instanceof ParameterizedType){
//如果屬于參數(shù)化類型率翅,獲得他的真實(shí)類型 getActualTypeArguments
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
//再次輸出真實(shí)的泛型信息
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("2:"+actualTypeArgument);
}
}
}
//獲得返回值類型
method = Test11.class.getMethod("test02",null);
Type genericReturnType = method.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType){
//如果genericReturnType返回值類型屬于參數(shù)化類型,獲得他的真實(shí)類型 getActualTypeArguments
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
//再次輸出真實(shí)的泛型信息
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("3:"+actualTypeArgument);
}
}
}
}
反射與注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
public class TestReflectAnnotation {
public static void main(String[] args) throws Exception {
TestAccountAnnotation testAccountAnnotation = new TestAccountAnnotation();
Class<?> class1 = TestAccountAnnotation.class;
Method method = class1.getMethod("show", String.class, int.class, String.class);
Account annotation = method.getAnnotation(Account.class);
String name = annotation.name();
int age = annotation.age();
String gender = annotation.gender();
method.invoke(testAccountAnnotation, name, age, gender);
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Account {
String name();
int age() default 18;
String gender();
}
class TestAccountAnnotation {
@Account(name = "法外狂徒", gender = "男")
public void show(String name, int age, String gen) {
System.out.println(name);
System.out.println(age);
System.out.println(gen);
}
}
執(zhí)行結(jié)果:
法外狂徒
18
男