可能我们有一个模糊的概念,反射性能会慢,但是有多慢没有一个具体的数据。那我就写代码来测试一下。
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毫秒。所以能不用反射,就尽量不用反射,实在不行,用也是可以的。