我看到下面的代码,并想知道编码器的意图。它与自动装箱的性能有关吗?是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