java reflect性能测试

java reflect性能测试

针对类的成员set,get方法和创建对象进行了正常和反射的测试。
测试前提:一千万次调用的测试,cpu e5800 @3.2GHz,内存3G

测试代码如下:

Cat.java

public class Cat {

    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

}


TestInvoke.java

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class TestInvoke {
    private static int testNum = 10000000;// 一千万次

    public static void main(String[] args) throws Exception {
        TestInvoke testInvoke = new TestInvoke();
        
        testInvoke.testSet_reflect();
        testInvoke.testSet_normal();

        testInvoke.testGet_reflect();
        testInvoke.testGet_normal();

        testInvoke.testNew_reflect();
        testInvoke.testNew_normal();
    }

    /**
     * set方法反射方式测试
     * 
     * @throws Exception
     */
    public void testSet_reflect() throws Exception {
        Map<String, Method> methodCache = new HashMap<String, Method>();
        Class<Cat> classType = Cat.class;
        Object object = classType.newInstance();

        String methodName = "setId";
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < testNum; i++) {
            // 如果setMethod直接放在循环里面性能下降10倍。所以可以做个缓存。
            Method setMethod = null;
            if (methodCache.containsKey(methodName)) {
                setMethod = methodCache.get(methodName);
            } else {
                setMethod = classType.getMethod(methodName, new Class[] {int.class});
                methodCache.put(methodName, setMethod);

            }
            setMethod.invoke(object, 100000);
        }
        System.out.println("reflect invoke set method spend time:" + (System.currentTimeMillis() - startTime));
    }

    /**
     * set方法正常方式测试
     * 
     * @throws Exception
     */
    public void testSet_normal() throws Exception {
        Cat cat = new Cat();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < testNum; i++) {
            cat.setId(100000);
        }
        System.out.println("normal  invoke set method spend time:" + (System.currentTimeMillis() - startTime));
    }

    /**
     * get方法反射方式测试
     * 
     * @throws Exception
     */
    public void testGet_reflect() throws Exception {
        Map<String, Method> methodCache = new HashMap<String, Method>();
        Class<Cat> classType = Cat.class;
        Object object = classType.newInstance();

        // 设置数据
        Method setMethod = classType.getMethod("setId", new Class[] {int.class});
        setMethod.invoke(object, 1234);

        String methodName = "getId";
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < testNum; i++) {
            // 如果setMethod直接放在循环里面性能下降10倍。所以可以做个缓存。
            Method getMethod = null;
            if (methodCache.containsKey(methodName)) {
                getMethod = methodCache.get(methodName);
            } else {
                getMethod = classType.getMethod(methodName);
                methodCache.put(methodName, getMethod);

            }
            getMethod.invoke(object);
        }
        System.out.println("reflect invoke get method spend time:" + (System.currentTimeMillis() - startTime));
    }

    /**
     * get方法正常方式测试
     * 
     * @throws Exception
     */
    public void testGet_normal() throws Exception {
        Cat cat = new Cat();
        // 设置数据
        cat.setId(1234);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < testNum; i++) {
            cat.getId();
        }
        System.out.println("normal  invoke get method spend time:" + (System.currentTimeMillis() - startTime));
    }

    /**
     * new方法反射方式测试
     * 
     * @throws Exception
     */
    public void testNew_reflect() throws Exception {
        long startTime = System.currentTimeMillis();
        Class<Cat> classType = Cat.class;
        for (int i = 0; i < testNum; i++) {
            Object object = classType.newInstance();
        }
        System.out.println("reflect invoke new spend time:" + (System.currentTimeMillis() - startTime));
    }

    /**
     * new方法正常方式测试
     * 
     * @throws Exception
     */
    public void testNew_normal() throws Exception {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < testNum; i++) {
            Cat cat = new Cat();
        }
        System.out.println("normal  invoke new spend time:" + (System.currentTimeMillis() - startTime));
    }

}



三次运行结果:
第一次:
reflect invoke set method spend time:1078
normal  invoke set method spend time:0(经常结果0,效率真是太高了)
reflect invoke get method spend time:1000
normal  invoke get method spend time:15
reflect invoke new spend time:1063
normal  invoke new spend time:109

第二次:
reflect invoke set method spend time:1078
normal  invoke set method spend time:16
reflect invoke get method spend time:1000
normal  invoke get method spend time:0(经常结果0,效率真是太高了)
reflect invoke new spend time:1063
normal  invoke new spend time:109


第三次:
reflect invoke set method spend time:1078
normal  invoke set method spend time:15
reflect invoke get method spend time:985
normal  invoke get method spend time:15
reflect invoke new spend time:1063
normal  invoke new spend time:109


得出以下结论:
1 反射不是不能用,没有想象的那么差,只是正常调用方式效率更高,在一千次内的调用可以认为效率相当。
2 set方法效率相差大概:70到来200倍
3 get方法效率相差大概:70到来200倍
4 new方法效率相差大概:10倍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值