Java反射和new效率對比,差距有多大
一. 基礎概念
Java中,一般我們創建一個對象可能會選擇new一下個實例。但是隨著我們技術的不斷提升,我們也學習到了,可以通過反射技術實現對象的創建。
可是,你有沒有想一下,什么時候我們改用new創建對象,什么時候我們改用反射創建對象呢?
兩者創建對象的效率又是如何呢?
//new 方式創建對象
ReflectDemo reflectDemo = new ReflectDemo();
//反射創建對象 反射創建對象的三種方式
(1)Class<ReflectDemo> reflectDemoClass = ReflectDemo.class;
(2)Class<?> aClass = Class.forName ("com.whale.springtransaction.transactiondemo.reflectdemo.ReflectDemo");
(3)Class<? extends Class> aClass = reflectDemoClass.getClass ();
二. new 對象和反射創建對象的效率對比
//測試代碼如下
public class ReflectDemo {
public static void main (String[] args) throws IllegalAccessException, InstantiationException {
proxyObject();
newObject();
}
//new 創建對象
//5
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耗時為:" + (endTime - startTime));
}
}
//反射 創建對象
//30
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 ("反射耗時為:" + (endTime - startTime));
}
}
}
圖片
最終我們發現,new 100000000
個對象和反射創建 100000000 個對象,效率相差了很多倍。
所以下面我們來探討一下為什么這么大差別?
首先第一點,一般我們的Java代碼是需要編譯后在虛擬機里面運行的。
我們一般都是通過一個前端編輯器,比如javac,把java文件轉為class文件。
接下來,程序運行期間,可能會通過一個JIT,即時編譯器將字節碼文件轉換為計算機認識的機器碼文件。
另外一種可能是通過一個AOT編譯器,直接把java文件編譯為本地機器碼文件。其中JIT在程序運行期會對程序進行優化,但是反射是通過動態解析的方式,因此可能無法執行某些java虛擬機的優化。
總結起來有下面幾個原因:
Method#invoke
方法會對參數做封裝和解封操作
- 需要檢查方法可見
- 需要校驗參數
- 反射方法難以內聯
- JIT 無法優化
三. 反射和new 的使用場景
反射的部分使用場景
- Spring通過反射來幫我們實例化對象,并放入到Ioc容器中
- 使用JDBC鏈接數據庫時加載數據庫驅動
Class.forName()
- 逆向代碼 例如反編譯
- 利用反射,在泛型為int的arryaList集合中存放一個String類型的對象
new 對象和反射的區別
- new的對象無法訪問其中的私有屬性,反射出來的可以通過設置
setAccessible()
方法來省略訪問權限符。 - new必須要知道類名,而反射創建對象不需要知道類型也可以創建