可能我們有一個模糊的概念,反射性能會慢,但是有多慢沒有一個具體的數據。那我就寫代碼來測試一下。
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毫秒。所以能不用反射,就盡量不用反射,實在不行,用也是可以的。
