Java应用反射的时候,性能往往是java程序员担心的地方,那么在大量运用反射的时候,性能的微弱提升,对这个系统而言都是如旱地逢甘霖。

 


下面用代码简单验证一下反射性能都损耗在哪里。

 


package littlehow.reflect.demo;

/**
 * WorkBean 作为反射性能测试的bean
 *
 * @author littlehow
 * @time 2016-06-13 14:27
 */
public class WorkBean {
    /**
     * 工作人名称
     */
    private String userName;
    /**
     * 公司名称
     */
    private String companyName;
    /**
     * 工作年限
     */
    private int workAge;
    /**
     * 薪资待遇
     */
    private double salary;

    /**
     * 无参构造
     */
    public WorkBean() {
        super();
    }

    /**
     * 姓名
     * @param userName
     */
    public WorkBean(String userName) {
        this.userName = userName;
    }

    /**
     * 姓名和公司名称的构造
     * @param userName
     * @param companyName
     */
    public WorkBean(String userName, String companyName) {
        this(userName);
        this.companyName = companyName;
    }

    /**
     * 工作
     */
    public void workAt(boolean flag) {
        System.out.println(this.userName+"在"+(flag?"上午":"下午")+"上午工作的时候一直在打瞌睡!");
    }

    /**
     * 工作
     * @param flag
     * @param message
     */
    public void workAt(boolean flag, String message) {
        System.out.println(this.userName+"在"+(flag?"上午":"下午")+message);
    }

    /**
     * 工作
     */
    public void workAt() {
        System.out.println(this.userName+"工作了好久了");
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    public int getWorkAge() {
        return workAge;
    }

    public void setWorkAge(int workAge) {
        this.workAge = workAge;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return this.userName + "在" + this.companyName + "工作了" + this.workAge + "年,现在的薪水是" + this.salary;
    }
}

 

 


然后是测试反射的demo

package littlehow.reflect.demo;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * ReflectDemo  反射性能消耗在哪里
 *
 * @author littlehow
 * @time 2016-06-13 14:41
 */
public class ReflectDemo {
    /**
     * 测试class
     */
    static Class<?> clazz = WorkBean.class;
    /**
     * 公用构造方法缓存
     */
    private static final HashMap<String, Constructor<?>> constructors = new HashMap<String, Constructor<?>>();
    /**
     * 公用method缓存
     */
    private static final ConcurrentHashMap<String, MethodCache> methods = new ConcurrentHashMap<String, MethodCache>();

    /**
     * 不经过优化的构造方法性能测试
     */
    @Test
    public void constructorNormalTest() {
        long start = System.currentTimeMillis();
        try {
            Object obj = null;
            for(int i = 0; i < 1000000; i ++) {
                Constructor<?> cons1 = clazz.getConstructor();
                obj = cons1.newInstance();
                Constructor<?> cons2 = clazz.getConstructor(String.class);
                obj = cons2.newInstance("littlehow");
                Constructor<?> cons3 = clazz.getConstructor(String.class, String.class);
                obj = cons3.newInstance("littlehow", "future company");
            }
            System.out.println(obj);//littlehow在future company工作了0年,现在的薪水是0.0
        } catch (Exception e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("use time : " + (end - start) + "ms");//平均840毫秒左右
    }

    /**
     * 对单一的进行缓存,速度最快,但功用性不够好
     * 相对于
     * @see constructorNormalTest()方法,性能提升10倍
     * 可见反射中对构造方法的获取非一个非常耗时的操作
     */
    @Test
    public void constrctorBufferOne() {
        long start = System.currentTimeMillis();
        try {
            Constructor<?> cons1 = clazz.getConstructor();
            Constructor<?> cons2 = clazz.getConstructor(String.class);
            Constructor<?> cons3 = clazz.getConstructor(String.class, String.class);
            Object obj = null;
            for(int i = 0; i < 1000000; i ++) {
                obj = cons1.newInstance();
                obj = cons2.newInstance("littlehow");
                obj = cons3.newInstance("littlehow", "future company");
            }
            System.out.println(obj);//littlehow在future company工作了0年,现在的薪水是0.0
        } catch (Exception e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("use time : " + (end - start) + "ms");//平均80毫秒左右
    }

    /**
     * key值的计算耗时也比较大,可以再进行优化
     * @param clazz
     * @param arguClass
     * @return
     * @throws NoSuchMethodException
     */
    private static Constructor<?> getConstrucor(Class<?> clazz, Class<?> ...arguClass) throws NoSuchMethodException {
        String key = clazz.getName();
        for (Class<?> argu : arguClass) {
            key = key + argu.getName();//这里会有编译优化
        }
        Constructor<?> constructor = constructors.get(key);
        if (constructor == null) {
            constructor = clazz.getConstructor(arguClass);
            constructors.put(key, constructor);
        }
        return constructor;
    }

    /**
     * 公用缓存,在性能和开发维护中这种处理,在性能要求不是超高的
     * 系统中可以选用该方式进行构造方法的缓存,提升开发速度
     * 效率相对第一个测试性能也提升了一倍多
     */
    @Test
    public void constructorBufferAll() {
        long start = System.currentTimeMillis();
        try {
            Constructor<?> cons1 = clazz.getConstructor();
            Constructor<?> cons2 = clazz.getConstructor(String.class);
            Constructor<?> cons3 = clazz.getConstructor(String.class, String.class);
            Object obj = null;
            for(int i = 0; i < 1000000; i ++) {
                obj = getConstrucor(clazz).newInstance();
                obj = getConstrucor(clazz, String.class).newInstance("littlehow");
                obj = getConstrucor(clazz, String.class, String.class).newInstance("littlehow", "future company");
            }
            System.out.println(obj);//littlehow在future company工作了0年,现在的薪水是0.0
        } catch (Exception e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("use time : " + (end - start) + "ms");//平均330毫秒左右
    }

    /**
     * 用class直接newInstance
   &nb