【发布时间】:2009-01-03 05:32:02
【问题描述】:
当 Java 编译器将原语自动装箱到包装类时,它会在幕后生成什么代码?我想它会调用:
- 包装器上的 valueOf() 方法
- 包装器的构造函数
- 其他魔法?
【问题讨论】:
标签: java autoboxing
当 Java 编译器将原语自动装箱到包装类时,它会在幕后生成什么代码?我想它会调用:
【问题讨论】:
标签: java autoboxing
您可以使用javap 工具亲自查看。编译如下代码:
public class AutoboxingTest
{
public static void main(String []args)
{
Integer a = 3;
int b = a;
}
}
编译和反汇编:
javac AutoboxingTest.java
javap -c AutoboxingTest
输出是:
Compiled from "AutoboxingTest.java"
public class AutoboxingTest extends java.lang.Object{
public AutoboxingTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_3
1: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: aload_1
6: invokevirtual #3; //Method java/lang/Integer.intValue:()I
9: istore_2
10: return
}
因此,如您所见,自动装箱会调用静态方法Integer.valueOf(),而自动拆箱会在给定的Integer 对象上调用intValue()。真的没有别的了 - 它只是语法糖。
【讨论】:
我想出了一个单元测试,证明调用 Integer.valueOf() 而不是包装器的构造函数。
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import org.junit.Test;
public class Boxing {
@Test
public void boxing() {
assertSame(5, 5);
assertNotSame(1000, 1000);
}
}
【讨论】:
如果您查找Integer#valueOf(int) 的 API 文档,您会发现它是在 JDK 1.5 中添加的。所有包装器类型(还没有)都添加了类似的方法来支持自动装箱。如 JLS 中所述,对于某些类型有额外的要求:
如果被装箱的值 p 是
true、false、byte、char,范围在\u0000到\u007f或int或short介于-128和127之间的数字,则令r1 和r2 为p 的任意两次装箱转换的结果. r1 == r2 总是如此。 §5.1.7
有趣的是,longs 不受相同要求的约束,尽管在 Sun 的实现中缓存了 -128..127 范围内的 Long 值,就像其他整数类型一样。
我还刚刚发现,在我的 The Java Programming Language 副本中,它说 char 值从 \u0000 到 \u00ff 被缓存,但当然每个规范的上限是 \u007f(和 Sun JDK在这种情况下符合规范)。
【讨论】:
我建议使用jad 之类的内容并大量反编译代码。你可以学到很多关于 java 实际在做什么。
【讨论】: