我看到下面的代碼,並想知道編碼器的意圖。它與自動裝箱的性能有關嗎?是Boolean.TRUE而不是真正的自動裝箱優化?
map.put("doesntMatter", Boolean.TRUE);
他可以這樣做:
map.put("doesntMatter", true);
做第一有什麼好處?
我看到下面的代碼,並想知道編碼器的意圖。它與自動裝箱的性能有關嗎?是Boolean.TRUE而不是真正的自動裝箱優化?
map.put("doesntMatter", Boolean.TRUE);
他可以這樣做:
map.put("doesntMatter", true);
做第一有什麼好處?
從源代碼 -
public static final Boolean TRUE = new Boolean(true);
public Boolean(boolean value) {
this.value = value;
}
private final boolean value;
因此,大家可以看到,TRUE
稱這只是設置值的構造。所以理論上它的效率稍低,因爲它做了一些額外的工作以獲得相同的結果。
我寫了一個例子:
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編譯器將執行它的工作並優化它。
我不確定我們在這裏看到的是什麼......請您詳細說明一下。也可以將它與'Map
@ Dgrin91:'Map
@ Dgrin91:這正是我所說的'invokestatic#26
的好處是不是在執行時間,因爲這個小測試代碼所示:
結果:
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));
}
}
我想說的編譯器非常聰明,所以任何這些都會產生同樣的效果。 - 但我們可以做這個測試。 – acdcjunior
無論是@acdcjunior表示,還是在運行時,JIT都會知道這一點。所以,最終沒有真正的利益。 – fge
剛剛通過ORACLE的'javap'進行檢查,並且好或不好,'map.put(「doesntMatter」,true)'被轉換爲'map.put(「doesntMatter」,Boolean.valueOf(1))''。所以它會生成一個額外的指令(在調用'valueOf'方法之前將'1'推入堆棧),並使用'invokestatic'而不是'getstatic'(在第一條語句中使用)。我很難從中得出任何結論(因爲JIT將在真正的時間到來時發揮作用;不同的編譯器會生成不同的字節碼),但是我剛剛描述的是Oracle的'javac'和'javap實際發生的情況'。 – acdcjunior