反射性能研究,反射赋值与set方法赋值对比

可能我们有一个模糊的概念,反射性能会慢,但是有多慢没有一个具体的数据。那我就写代码来测试一下。

package com.itbac.reflection;

import java.lang.reflect.Field;

public class test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        long begin = System.currentTimeMillis();
        Book book = new Book();
        book.setName("java从入门到放弃");
        book.setNum(1);
        book.setPrice(1.2);
        System.out.println(book.toString());
              //循环一千万次
        for (int i = 0; i < 10000000; i++) {
            //1.set方法赋值  耗时毫秒:7
//            book.setNum(++i);

            //2.反射赋值  耗时毫秒:1045
            setFeild(book, i,"num");
        }
        System.out.println(book.toString());
        long end = System.currentTimeMillis();
        System.out.println("毫秒:"+(end-begin));
    }

    private static void setFeild(Book book, int i,String str) throws NoSuchFieldException, IllegalAccessException {
        Class<? extends Book> aClass = book.getClass();
        Field num = aClass.getDeclaredField(str);
        num.setAccessible(true);
        num.set(book, i);
    }
}

通过上面的测试,我发现在循环赋值一千万次的时候,反射耗时一秒。这个慢才能被人所感知。如果你的反射调用,少于一千万次,请不要说反射慢。

再看两个方法的对比,set方法直接就能赋值,反射方法还需要获取Class 和 Field ,设置访问权限,好几部操作。我可以用一个map来优化一下。

package com.itbac.reflection;

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

public class test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        long begin = System.currentTimeMillis();
        Book book = new Book();
        book.setName("java从入门到放弃");
        book.setNum(1);
        book.setPrice(1.2);
        System.out.println(book.toString());
        Map<String, Field> map = new HashMap<>();
              //循环一千万次
        for (int i = 0; i < 10000000; i++) {
            //1.set方法赋值  耗时毫秒:7
//            book.setNum(++i);

            //2.反射赋值(没有用map)  耗时毫秒:1045
            //3.反射赋值(使用map缓存Field)  耗时毫秒:95
            setFeild(book, i,"num",map);
        }
        System.out.println(book.toString());
        long end = System.currentTimeMillis();
        System.out.println("耗时毫秒:"+(end-begin));
    }

    private static void setFeild(Book book, int i,String str,Map<String, Field> map) throws NoSuchFieldException, IllegalAccessException {
        Field field = map.get(str);
        if (null == field) {
            Class<? extends Book> aClass = book.getClass();
            field= aClass.getDeclaredField(str);
            field.setAccessible(true);
            map.put(str, field);
        }
        field.set(book, i);
    }
}

这样处理,得出一个数据,95 除以 7  约等于 13.5  ,得出结论,在一千万次调用,反射赋值比直接赋值慢了 13.5倍。

但是,反射赋值一千万次,才耗时95毫秒,是人无法感知的速度。是可以被我们接受的程序代码运行速度。

我试着提高反射的次数,看看多少次,才能被我们感觉到慢呢。

代码运行结果如下:

一亿次反射赋值,耗时毫秒:687

两亿次反射赋值,耗时毫秒:1468

个人的结论:

  反射赋值是比直接赋值慢,但是你在一亿次调用以内,你是感觉不到它慢的,可以放心使用。

当然,set方法赋值更变态,2亿次赋值,耗时15毫秒。所以能不用反射,就尽量不用反射,实在不行,用也是可以的。

原文地址:https://www.cnblogs.com/itbac/p/11963086.html