2013-06-21 35 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)); 
    } 
}