自动装箱、拆箱的内幕:
自动装箱与拆箱的功能事实上是编译程序蜜糖( Compiler Sugar),也就是编译程序让你撰写程序时吃点甜头,编译时期根据所撰写的语法,决定是否进行装箱或拆箱动作。
Integer num=1;//自动装箱,编译程序自动展开为:
Integer localInteger=Integer.valueOf(1);
int foo=num;//自动拆箱
System.out.println(num+10);
num+10中先对num拆箱再进行运算。
Integer localInteger=Integer.valueOf(1);
这也是为基本类型建立打包器的方式之一。了解编译程序会如何装箱与拆箱是必要的,例如下面的程序是可以通过编译的
Integer i=null;
int j=i;
但
是在执行时期会有错误,因为编译程序会将之展开为
Object localObject=null;
int i=localObject.intValue();
在Java程序代码中,null代表一个特殊对象,任何类声明的参考名称都可以参考至null,表示该名称没有参考至任何对象实体,这相当于有个名牌没有任何人佩戴。在上例中,由于并没有参考至任何对象,所以就不可能操作
intValue方法,就相当于有个名牌没有人佩戴,你却要求戴名牌的人举手,这是一种错误.
编译程序蜜糖通常提供了方便性,但也因此隐藏了一些细节,所以别只顾着吃糖而忽略了该知道的概念。
Integer num=100;
Integer num1=100;
if(num==num1) {
System.out.println("num=num1");
}else {
System.out.println("num!=num1");
}
如果只看就好像直接进行比较,有的人会理所当然回答显示
num=num1
那么下面这个:
Integer num=200;
Integer num1=200;
if(num==num1) {
System.out.println("num=num1");
}else {
System.out.println("num!=num1");
}
程序代码只不过将100改为200,但执行结果会显示
num!=num1
前面提过,自动装箱是编译程序蜜糖。以上例来说,实际上会使用Integer.valueof()来建立Integer实例,所以你要知道
Integer.valueof()到底如何建立 Integer实例。查查JDK文件夹src.zip中的 java/lang文件夹中的 Integer.java,你会看到 :
public static Integer valueOf(int i) {
if(i>=IntegerCache.low&&i>=IntegerCache.high)
return IntegerCache.cache(i+(-IntegerCache.low));
return new Integer(i);
}
这段程序代码简单来说,就是如果传入的int在
IntegerCache.low和integerCache.high
之间,那就尝试看看前血缓存( Cache)中有没有打包过相同的值,如果有就直接返回,否则就使用new创建新的 Integer实例
IntegerCache.low
默认值是-128,
integerCache.high
默认值是127
Integercache是 Integer类别内部实作中的一个类,缓存会在首次使用到 Integercache类时建立。
Integer num=100;
Integer num1=100;
第一行程序代码由于100在-128~127之间,会从缓存中传回 Integer实例,第二行程序代码执行时,要打包的同样是100,也是从缓存中返回同一 Integer实例,所以会参考到同一个 Integer实例,使用比较就会是true
如果是这个程序代码
Integer num=200;
Integer num1=200;
第一行程序代码由于200不在-128~127之间,所以直接建立 Integer实例,第二行程序代码执行时,也是直接建立新的 Integer实例,所以num1与num2不会参考到同一个 Integer实例,两个不同实例,使用==比较就会是false。
Integercache.low默认值是-128, IntegerCache.high默认值是127 ,执行时期无法更改可以在启动JVM时,使用系统属性java. lang.Integer.IntegerCache.high来指定。java. lang.Integer.IntegerCache.high=300就会针对-128~300范围中建立的打包器进行快速存取.
在IDE中,也可以指定JVM启动时可用的一些自变量。例如在 Netbeans中,可以这样操作进行设定
(1)在项目上右击,在弹出的快捷菜单中选择“属性”命令,打开“项目属性”对话框在“类别”列表中选择“运行”节点
(2)单击“配置”列表框后面的“新建”按钮,打开“创建新的配置”对话框,在“配置名称”文本框中输入配置文件名称,然后单击“确定”按钮
(3)在“主类”文本框中输入与程序进入点的类完全吻合名称
(4)在“VM选项”文本框中输入- Djava. lang. Integer.IntegerCache.high=300,单击“确定”按钮完成设定
这样设定之后,每次在菜单中选择“运行”|“运行主项目”命令时,就会套用“VM选项”中的设定.
所以结论值比较时,别使用==或!=来比较两个对象实质内容值是否相同(因为与!=是比较对象参考),而要使用 equals()
Integer num=200;
Integer num1=200;
if(num.equals(num2)) {
System.out.println("num=num1");
}else {
System.out.println("num!=num1");
}