2013-06-21 38 views
1

我看到下面的代碼,並想知道編碼器的意圖。它與自動裝箱的性能有關嗎?是Boolean.TRUE而不是真正的自動裝箱優化?

map.put("doesntMatter", Boolean.TRUE); 

他可以這樣做:

map.put("doesntMatter", true); 

做第一有什麼好處?

+0

我想說的編譯器非常聰明,所以任何這些都會產生同樣的效果。 - 但我們可以做這個測試。 – acdcjunior

+0

無論是@acdcjunior表示,還是在運行時,JIT都會知道這一點。所以,最終沒有真正的利益。 – fge

+1

剛剛通過ORACLE的'javap'進行檢查,並且好或不好,'map.put(「doesntMatter」,true)'被轉換爲'map.put(「doesntMatter」,Boolean.valueOf(1))''。所以它會生成一個額外的指令(在調用'valueOf'方法之前將'1'推入堆棧),並使用'invokestatic'而不是'getstatic'(在第一條語句中使用)。我很難從中得出任何結論(因爲JIT將在真正的時間到來時發揮作用;不同的編譯器會生成不同的字節碼),但是我剛剛描述的是Oracle的'javac'和'javap實際發生的情況'。 – acdcjunior

回答

0

從源代碼 -

public static final Boolean TRUE = new Boolean(true); 

public Boolean(boolean value) { 
    this.value = value; 
} 

private final boolean value; 

因此,大家可以看到,TRUE稱這只是設置值的構造。所以理論上它的效率稍低,因爲它做了一些額外的工作以獲得相同的結果。

+1

你確定嗎? TRUE值被設置爲「靜態」。 – Raedwald

+1

'Boolean.TRUE'不調用構造函數。當類加載時,構造函數只調用一次。 'Boolean.TRUE'只是取消引用創建的對象。 – jlordo

+0

@jlordo糟糕,你是對的。我誤解了這一點。 –

4

我寫了一個例子:

public class Demo { 

    Map<String, Boolean> map = new HashMap<>(); 

    void primitive() { 
     map.put("a", true); 
    } 

    void object() { 
     map.put("b", Boolean.TRUE); 
    } 
} 

看的​​

0 aload_0 
1 getfield #17 <Demo/map Ljava/util/Map;> 
4 ldC#24 <a> 
6 iconst_1 
7 invokestatiC#26 <java/lang/Boolean/valueOf(Z)Ljava/lang/Boolean;> 
10 invokeinterface #32 <java/util/Map/put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;> count 3 
15 pop 
16 return 

字節碼和object()

0 aload_0 
1 getfield #17 <Demo/map Ljava/util/Map;> 
4 ldC#39 <b> 
6 getstatiC#41 <java/lang/Boolean/TRUE Ljava/lang/Boolean;> 
9 invokeinterface #32 <java/util/Map/put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;> count 3 
14 pop 
15 return 

結論的字節碼:

使用原語時,有一個額外的步驟調用Boolean.valueOf(),但如果您經常運行這段代碼,JIT編譯器將執行它的工作並優化它。

+0

我不確定我們在這裏看到的是什麼......請您詳細說明一下。也可以將它與'Map '進行比較? –

+2

@ Dgrin91:'Map '不會編譯。我寫了一個簡短的結論。 – jlordo

+0

@ Dgrin91:這正是我所說的'invokestatic#26 '。 –

1

的好處是不是在執行時間,因爲這個小測試代碼所示:

結果:

Time with primitives : 3334779619 
Time with Object : 4092034749 
Time with primitives : 3670851766 
Time with Object : 2748035018 
Time with Object : 3738916372 
Time with primitives : 2975196722 
Time with Object : 2514328271 
Time with primitives : 2588980283 
Time with Object : 2696162369 
Time with primitives : 2615258656 
Time with primitives : 2633824223 
Time with Object : 2489779261 

代碼:

import java.util.HashMap; 
import java.util.Map; 

import javax.swing.JOptionPane; 

public class Test 
{ 
    public static void main(String[] args) { 
    JOptionPane.showMessageDialog(null, "Start"); 

    createWithPrimitive(); 
    createWithObject(); 
    createWithPrimitive(); 
    createWithObject(); 
    createWithObject(); 
    createWithPrimitive(); 
    createWithObject(); 
    createWithPrimitive(); 
    createWithObject(); 
    createWithPrimitive(); 
    createWithPrimitive(); 
    createWithObject(); 

    System.exit(0); 
    } 

    private static void createWithObject() { 
    long time = System.nanoTime(); 
    Map<Integer, Boolean> testMap = new HashMap<Integer, Boolean>(); 
    for (int i = 1; i <= 10000000; i++) { 
     if (i % 2 == 0) { 
     testMap.put(i, Boolean.TRUE); 
     } else { 
     testMap.put(i, Boolean.FALSE); 
     } 
    } 

    System.out.println("Time with Object : " + (System.nanoTime() - time)); 
    } 

    private static void createWithPrimitive() { 
    long time = System.nanoTime(); 
    Map<Integer, Boolean> testMap = new HashMap<Integer, Boolean>(); 
    for (int i = 1; i <= 10000000; i++) { 
     if (i % 2 == 0) { 
     testMap.put(i, true); 
     } else { 
     testMap.put(i, false); 
     } 
    } 

    System.out.println("Time with primitives : " + (System.nanoTime() - time)); 
    } 
}