接触反射
之前遇到一个问题,移除List中count大于10的Object并返回移除后的List。最初我认为Stream流完全可以解决这个问题,而且代码精简。只需一行代码即可
List<Objetc> filtered = strings.stream().filter(item-> item.count > 10).collect(Collectors.toList());
然后接到需求,说10太大了,改成5.这个时候我自己都不知道写了多少处,修改起来风险很大,也不确实count是否还会再变。于是就开始接触泛型和反射。
public static <T> void removeUser(List<T> list) throws Exception{
if(null != list && list.size() > 0) {
Iterator<T> iterator = list.iterator();
while(iterator.hasNext()) {
T t = iterator.next();
Field field = t.getClass().getDeclaredField("count");
field.setAccessible(true); // 私有属性必须设置访问权限
Object resultValue = field.get(t);
int enpCount = Integer.parseInt(resultValue.toString());
if(enpCount > 0) {
iterator.remove();
}
}
}
}
下次count再变,只需修改一个地方即可
什么是反射
动态获取信息以及动态调用对象的方法的功能
反射能做什么
-
在运行状态中,对于任意一个类,都能够知道这个类的所有属性、方法和构造器
-
对于任意一个对象,都能够调用它的任意一个方法和属性
使用场合
在编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息。
不足
-
性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。
-
使用反射会模糊程序内部逻辑:程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。
怎么实现
常用的四个类
-
Class类 反射的核心类,可以获取类的属性,方法等信息。
-
Constructor类 表示类的构造方法。
-
Method类 表示类的方法,它可以用来获取类中的方法信息或者执行方法。
-
Field类 表示类的成员变量,可以用来获取和设置类之中的属性值
Class类
获取Class对象的三种方法
-
Object类中的getClass()方法
Class clazz = new User().getClass(); -
通过给定类的字符串名称就可以获取该类
Class<?> clazz = Class.forName("com.zjy.service.UserService"); -
对象静态属性 .class来获取对应的Class对象
Class<User> userClass = User.class;
Constructor类
获取Constructor
-
Constructor[] getConstructors():获得所有public构造器
-
Constructor[] getDeclaredConstructors():获得所有访问权限的构造器
-
Constructor getConstructor(Class[] params):根据指定参数获得对应构造器
-
Constructor getDeclaredConstructor(Class[] params):根据指定参数获得对应构造器;
常用方法
- String getName() 构造函数的名称
- int getModifiers() 返回方法的访问权限。返回值为int类型。想要转为访问权限,需要使用 Modify.toString()
- Class<?>[] getParameterTypes() 返回构造器的参数类型集合
Method类
获取Method
-
Method[] getMethods():获得所有public方法
-
Method[] getDeclaredMethods():获得所有访问权限的方法;但不包括继承方法。
-
Method getMethod(String name, Class[] params):根据方法签名获取类自身对应public方法,或者从基类继承和接口实现的对应public方法;
-
Method getDeclaredMethod(String name, Class[] params):根据方法签名获得对应的类自身的声明方法,访问权限不限;
常用方法
-
Object invoke(Object obj, object... args)
-
object obj 调用基础方法的对象,可以通过构造器实例该对象获取clazz.getConstructor().newInstance()
-
object... args 参数
-
Class<?>[] getParameterTypes() 返回方法参数类型集合
-
Class<?> getReturnType() 返回返回类型
-
String getName() 方法名
-
int getModifiers() 返回方法的访问权限。返回值为int类型。想要转为访问权限,需要使用 Modify.toString()
Field类
获取Field
-
Field[] getFields():获得类中所有public变量
-
Field[] getDeclaredFields():获得类中所有访问权限变量但不包括继承字段。
-
Field getField(String name):根据变量名得到对应的public变量
-
Field getDeclaredField(String name):根据变量名获得对应的变量,访问权限不限;
常用方法
-
Class<?> getType():获取字段的类型
-
String getName() 获取属性名称
-
Type getGenericType():获取字段的泛型类型
-
int getModifiers():返回方法的访问权限。返回值为int类型。想要转为访问权限,需要使用 Modify.toString()