在我們的日常使用中,Java new是用的最多的,但是有些框架往往會使用Java反射來實現靈活性,那么它們之間的效率有什么區別呢?
你有沒有想過,什么時候應該該用new來創建對象,什么時候該使用反射呢?
兩者之間創建對象的效率如何?
ReflectDemo reflectDemo = new ReflectDemo();Class<ReflectDemo> reflectDemoClass = ReflectDemo.class;Class<?> aClass = Class.forName ("com.jason.sample.ReflectDemo");Class<? extends Class> aClass = reflectDemoClass.getClass ();
1. new 對象和反射創建對象的效率對比
public class ReflectDemo { public static void main (String[] args) throws IllegalAccessException, InstantiationException { proxyObject(); newObject(); } public static void newObject(){ long startTime = System.currentTimeMillis (); int i; for (i = 0; i < 100000000; i++) { ReflectDemo reflectDemo = new ReflectDemo (); } if (i == 100000000) { long endTime = System.currentTimeMillis (); System.out.println ("new time:" + (endTime - startTime)); } } public static void proxyObject() throws IllegalAccessException, InstantiationException { long startTime = System.currentTimeMillis (); Class<ReflectDemo> reflectDemoClass = ReflectDemo.class; int i; for (i = 0; i < 100000000; i++) { ReflectDemo reflectDemo = reflectDemoClass.newInstance (); } if (i == 100000000) { long endTime = System.currentTimeMillis (); System.out.println ("reflection time:" + (endTime - startTime)); } }}new time:3reflection time:230
最后我們發現新建1億個對象和反射創建1億個對象的效率相差很多倍。
那么讓我們來探討一下為什么會有如此大的差異。
一般來說,我們的Java代碼需要在虛擬機上編譯運行。
一般通過前端編輯器將java文件轉換成class文件,比如javac.
接下來,在程序執行期間,JIT(即時編譯器)可以將字節碼文件轉換為計算機可識別的機器碼文件。另一種方式是通過 AOT 編譯器直接將 java 文件編譯成本地機器碼文件。其中JIT會在程序運行時對程序進行優化,但是反射是通過動態分析的,所以可能無法對Java虛擬機進行一些優化。
總結起來有以下幾個原因:
- 反射需要動態解析類信息:在使用反射創建對象時,需要使用Class.forName()方法或類的class屬性等方式獲取類的信息。這個過程需要在運行時進行,而使用new關鍵字則在編譯時已經解析了類信息,所以不需要進行類信息解析。
- 反射需要查找并調用構造函數:使用反射創建對象需要先獲取構造函數對象,然后通過反射調用構造函數進行對象創建。這個過程需要在運行時進行,而使用new關鍵字則直接調用構造函數進行對象創建,無需查找構造函數。
- 反射需要進行安全性檢查:使用反射創建對象時,Java會對代碼進行安全性檢查,以確保反射調用的方法和構造函數是可訪問的。這個過程也需要在運行時進行,而使用new關鍵字則不需要進行安全性檢查。
- 反射創建的對象需要做額外的初始化工作:使用反射創建的對象需要進行額外的初始化工作,例如調用對象的setAccessible(true)方法以訪問私有成員變量和方法等。這些額外的操作也會增加反射創建對象的時間。
綜上所述,Java反射比使用new關鍵字創建對象的性能差,因為反射需要在運行時進行更多的操作,包括動態解析類信息、查找并調用構造函數、進行安全性檢查和進行額外的初始化工作等。在性能要求較高的場景中,應該盡可能地避免使用反射創建對象,而盡量使用new關鍵字進行對象創建。
2、反射的使用場景反射的一些使用場景