Java反射

135 阅读4分钟

接触反射

之前遇到一个问题,移除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()

脑图

地址: github.com/zhaojinyi/m…