反射的使用
通过反射查看类信息
- 类的构造方法:Class类提供了用于获取某个类的构造方法。
Constructor getConstructor(Class<?>... parameterTypes) 根据构造函数的参数,返回一个具体的具有public属性的构造函数
Constructor getConstructors() 返回所有具有public属性的构造函数数组
Constructor getDeclaredConstructor(Class<?>... parameterTypes) 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
Constructor getDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
- 类的属性:Class类提供了获取成员属性的方法
Field getField(String name) 根据变量名,返回一个具体的具有public属性的成员变量
Field[] getFields() 返回具有public属性的成员变量的数组
Field getDeclaredField(String name) 根据变量名,返回一个成员变量(不分public和非public属性)
Field[] getDelcaredFields() 返回所有成员变量组成的数组(不分public和非public属性)
- 类的方法:Class类提供了获取成员方法的方法
Method getMethod(String name, Class<?>... parameterTypes) 根据方法名和参数,返回一个具体的具有public属性的方法
Method[] getMethods() 返回所有具有public属性的方法数组
Method getDeclaredMethod(String name, Class<?>... parameterTypes) 根据方法名和参数,返回一个具体的方法(不分public和非public属性)
Method[] getDeclaredMethods() 返回该类中的所有的方法数组(不分public和非public属性)
通过反射生成并操作对象代码实例:
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);
}
//获取指定的方法 重载,所以要添加参数
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、获取指定的构造器
System.out.println("=================================");
Constructor[] constructors = c1.getConstructors();//获取public
for (Constructor constructor : constructors) {
System.out.println("c1.getConstructors():"+constructor);
}
Constructor[] constructors1 = c1.getDeclaredConstructors();//获取所有的构造器
for (Constructor constructor : constructors1) {
System.out.println("c1.getDeclaredConstructors():"+constructor);
}
//获取指定的构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println("获取指定的构造器"+declaredConstructor);//获取指定的构造器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 + "]";
}
}
通过反射调用对象方法
public class TestInvoke {
public String invokeMethod() {
System.out.println("invokeMethod已执行!");
return "invokeMethod已执行!";
}
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.创建对象
TestInvoke testInvoke = (TestInvoke) stuClass.newInstance();
//4.调用invokeMethod()方法
String retrunStr = (String) method.invoke(testInvoke, null);
System.out.println("获取方法执行后的返回值:"+retrunStr);
}
}
通过反射执行类方法的步骤:
- 通过反射获取Class对象
- 通过getMethod()指定方法名获取方法
- 通过反射获取的Class类创建实例对象
- 通过invoke()执行指定方法
反射与泛型
Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除。
通过反射越过泛型检查:
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对象,反向的调用add()方法,添加数据
Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象
//获取add()方法
Method method = listClass.getMethod("add", Object.class);
//调用add()方法
method.invoke(strList, "数字");
//遍历集合
for (Object obj : strList) {
System.out.println(obj);
}
}
}
执行结果:
100
200
数字
为了通过反射操作泛型代表的类型,Java新增了ParameterizedType
,GenericArrayType
,TypeVariable
和WildcardType
几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。
类型 | 说明 |
---|---|
ParameterizedType | 表示一种参数化类型,比如Collection< String > |
GenericArrayType | 表示一种元素类型是参数化类型或者类型变量的数组类型 |
TypeVariable | 是各种类型变量的公共父接口 |
WildcardType | 代表一种通配符类型表达式 |
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 {
//获得参数类型
Method method = Test11.class.getMethod("test01", Map.class, List.class);
//获取参数类型 即Map和 List
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("1:"+genericParameterType);
//判断genericParameterType参数类型 是否属于 ParameterizedType 参数化类型
if (genericParameterType instanceof ParameterizedType){
//如果属于参数化类型,获得他的真实类型 getActualTypeArguments
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
//再次输出真实的泛型信息
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("2:"+actualTypeArgument);
}
}
}
//获得返回值类型
method = Test11.class.getMethod("test02",null);
Type genericReturnType = method.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType){
//如果genericReturnType返回值类型属于参数化类型,获得他的真实类型 getActualTypeArguments
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
//再次输出真实的泛型信息
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);
}
}
执行结果:
法外狂徒
18
男
网友评论