安利一个优雅的Java反射工具

2019-05-09  本文已影响0人  风云不羁

Java开发中或多或少的会用到反射的方式,通常的反射方式调用如下:

    public class Person {
        private String name;

        public Person(String name) {
            this.name = name;
        }

        private void setName(String name) {
            this.name = name;
        }
    }

    public String getPersonName(Person person) {
        Class pClass = person.getClass();
        try {
            Field nameField = pClass.getDeclaredField("name");
            return (String) nameField.get(person);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return null;
    }
    
    public void setPersonName(Person person, String name) {
        Class pClass = person.getClass();
        try {
            Method setName;
            setName = pClass.getDeclaredMethod("setName", pClass, String.class);
            setName.setAccessible(true);
            setName.invoke(person, name);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

每一次的反射调用都让人觉得代码有很多冗余的地方,我们总是希望调用的代码显得优雅而简洁。
下面就让我们来欣赏一下优雅的方式:

    public String getName(Person person) {
        try {
            return Reflect.on(person).get("name");
        } catch (Reflect.ReflectException e) {
            return null;
        }
    }
    
    public void setName(Person person, String name) {
        try {
            Reflect.on(person).call("setName", name);
        } catch (Reflect.ReflectException e) {
            e.printStackTrace();
        }
    }

该反射工具的源码地址 jOOR
这个工具的封装的功能基本覆盖反射调用所有方式,感兴趣的看官可以去看一下源码及使用方式。另外该库还支持Java代码的运行时编译:

Supplier<String> supplier = Reflect.compile(
    "com.example.HelloWorld",
    "package com.example;\n" +
    "class HelloWorld implements java.util.function.Supplier<String> {\n" +
    "    public String get() {\n" +
    "        return \"Hello World!\";\n" +
    "    }\n" +
    "}\n").create().get();

// Prints "Hello World!"
System.out.println(supplier.get());

扩展

如果项目中同一种反射的调用次数比较频繁的情况下,可以做缓存处理,避免每次都直接反射属性或者方法:

    //缓存ClassName对应的Class
    private static ConcurrentHashMap<String, Class> classCache;
    //缓存属性值
    private static ConcurrentHashMap<String, Field> fieldCache;
    //缓存方法
    private static ConcurrentHashMap<String, Method> methodCache;

    static {
        classCache = new ConcurrentHashMap<>();
        fieldCache = new ConcurrentHashMap<>();
        methodCache = new ConcurrentHashMap<>();
    }
上一篇下一篇

猜你喜欢

热点阅读