Java反射实现通用编程的应用

1. Java的反射应用 - 通用编程

实体类

public class User {
    private Integer id;
    private String name;
    public User() {}
    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    @Override
    public String toString() {
        return "User{" + "id=" + id + ", name='" + name + '\'' + '}';
    }
}

1.1 反射执行任意实体类对象的 set 方法

public class TestReflectMethod {
    public static void main(String[] args) throws Exception {
        User user = new User();
        setValue(user, "id", 10);
        setValue(user, "name", "hello,world");
        System.out.println(user); // User{id=10, name='hello,world'}
    }

    /**
     * 给指定对象的指定属性设置指定值
     * @param obj 指定的对象
     * @param fieldName 指定的属性名
     * @param value 指定的属性值
     */
    public static void setValue(Object obj, String fieldName, Object value) throws Exception {
        Class<?> objClass = obj.getClass();
        // 根据小驼峰命名规范获取 set 方法名,eg: setName
        String methodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
        System.out.println(methodName);
        Field field = objClass.getDeclaredField(fieldName);
        // 获取到属性类型
        Class<?> fieldType = field.getType();
        // 获取到 set 方法
        Method method = objClass.getMethod(methodName, fieldType);
        method.invoke(obj, value);
    }
}

1.2 反射执行任意实体类对象的 get 方法

public class TestReflectMethodGet {
    public static void main(String[] args) throws Exception {
        /* 实体类的 set/get 方法通用调用示例 */
        User user = new User(10, "小黑");
        Object id = getValue(user, "id");
        Object name = getValue(user, "name");
        System.out.println(id + ":" + name); // 10:小黑
    }

    /**
     * 从指定对象的指定属性获取属性值
     * @param obj 指定对象
     * @param fieldName 指定属性
     * @return Object类型值
     */
    public static Object getValue(Object obj, String fieldName) throws Exception {
        Class<?> objClass = obj.getClass();
        // 根据小驼峰命名规范获取 get 方法名,eg: getName
        String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
        // 获取到 get 方法
        Method method = objClass.getDeclaredMethod(methodName, (Class<?>[]) null);
        return method.invoke(obj, (Object[]) null);
    }
}

1.3 反射执行任意实体类对象的任意方法

import java.lang.reflect.Method;
public class TestInvokeAnything {
      public static void main(String[] args) throws Exception {
            // invokeAny() 执行任何方法
            // 传入:对象(Object)、方法名称(String)、形参(.class)、实参(Object)
            invokeAny(
                          createObject("com.day.t1_factory.Student"),
                          "exam",
                          new Class[] {int.class, double.class,  String.class},
                          2, 10, "小明"
                         ); // public void exam(int n, double score,  String name)
            
            Object o = createObject("com.day.t1_factory.Student");
            invokeAny(o, "study", null, null); // public void study()
            invokeAny(o, "study", new Class[] {Integer.class}, 100); //  public int study(Integer a)
            
      }
      /**
       * 反射技术,执行任何方法
       * @param obj Objcet类型对象
       * @param methodName String类型方法名称
       * @param types Class[]数组类型的types
       * @param args Object类型的可变长参数
       * @throws Exception
       */
      public static void invokeAny(Object obj, String methodName,  Class<?>[] types, Object...args) throws Exception {
            Class<?> c = obj.getClass(); // 1.获取类对象
            Method m = c.getDeclaredMethod(methodName, types); // 2.获得方法的对象Method
            m.invoke(obj, args); // 3.执行方法
      }
      /**
       * 反射技术,工厂设计模式
       * @param className 类的全限定名
       * @return 返回Object类型的对象
       */
      public static Object createObject(String className) {
            try {
                  Class<?> c = Class.forName(className);
                  return c.newInstance();
            } catch (Exception e) {
                  e.printStackTrace();
            }
            return null;
      }
}

1.4 读取配置文件反射创建任意实体对象

public class TestReflectConfigFile {
    public static void main(String[] args) throws Exception {
        User user = (User) getInstanceFromConfigFile("config.properties", "userClassName");
        System.out.println(user);
    }

    /**
     * 通过配置文件获取并创建指定键的类的实例对象
     * @param fileName 配置文件名称
     * @param key 配置文件中的键
     * @return Object对象
     */
    public static Object getInstanceFromConfigFile(String fileName, String key) throws Exception {
        Properties properties = new Properties();
        // 获取文件的 字节输入流
        InputStream is = TestReflectConfigFile.class.getClassLoader().getResourceAsStream(fileName);
        // 将流加载到 properties(map键值映射)
        properties.load(is);
        // 获取类全名
        String className = properties.getProperty(key);
        // 创建对象并返回
        return Class.forName(className).newInstance();
    }
}
/*
 * config.properties 配置文件内容:
 * userClassName=com.demo.reflect.User
 */

发布了320 篇原创文章 · 获赞 311 · 访问量 66万+

猜你喜欢

转载自blog.csdn.net/sinat_36184075/article/details/105520509