今天学习了java 包装器,其中有很有意思的东西,也应该着重注意的就是“128陷阱”,如果不把他真的弄明白,可能会对以后的编程生涯有很大影响
在奔向主体"128陷阱"之前我们先了解一下以下概念
比较的方法
1、在我们的印象中,所谓的比较就应该是“==”,比如
int a=100;
int b=100;
System.out.println(a==b);
对于以上代码,毫无疑问应该输出( true ),因为100就是等于100的
但是当“==”遇上了 “引用类型变量”,可能就会碰撞出不一样的火花
String a="abc";
String b="abc";
System.out.println(a==b);
你认为他会输出什么呢?
答案是 true ,但是这里我要解释一下,这里输出true 是因为 String 类型的变量 a 和 b 所指的地址是相同的,存储结构如图:
2、equals 方法
此方式是Object 类提供的比较方法,对两者值进行比较
String b=10;
String c=new String(10);
System.out.println(b==c);
System.out.println(c.equals(b));
以上代码输出结果是
flase
true
正好验证了两种方法的不同,因为c 指向的是又重新生成的对象,所以两个保存的地址值是不同的,但是其指向的对象的值是相同的。
包装器
有时需要将 int double 等基本类型转换为对象,所以基本类型都会有一个一直对应的包装器
int – > Integer
long – > Long
float --> Float
double -->Double
short --> Short
char --> Character
byte – > Byte
boolean --> Boolean
其中很重要的 就是 自动装箱 和自动拆箱
Integer a=10;//语句1
上面的语句看上去只是一个简单的赋值语句,其实另有玄机
他的完整写法是这样的
Integer a = new Integer(10);
或者说语句1执行的隐藏语句是:
Integer a = Integer.valueof(10); //这就是自动装箱过程
上面两个语句是差不多的多能表名,此时的 “10” 是一个Integer 类型的对象
是不是好奇自动拆箱是什么样子的,下面一个例子让你豁然开朗
Integer a=10;
Integer b= a+5;
这两句话虽然看似简单其实其中包含了自动装箱和自动拆箱的步骤,把它展开是这样的
Integer a=10;//这里是第一次自动装箱
//赋值语句从右向左看
a+5;//这里将a进行自动拆箱,与5进行运算得到结果15,此时15 正是一个基本类型的数值
Integer b=a+5;//将15进行自动装箱成为Integer 类型的对象,并将地址值赋给 b
!!!好下面才是最重要的部分
包装器128陷阱
Integer a=1000;
Integer b=1000;
System.out.println(a==b);
按照上面对 比较方法和包装器哔哔的内容,这个输出结果理应是 : true
但是他居然输出了 :flase
这个就有点坑*啦,原因是什么呢
话不多说,看源码:
由valueof函数的源代码可以看到,其中有一个限制条件 IntegerCache.Low和IntegerCache.high ,由于好奇心,我们再看一下这个东东的源代码
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
从代码中可以看出,所谓的IntegerCache.Low和IntegerCache.high 的值为-128和127 ,所以超过这个范围的Integer 对象都是重新建立的跟之前的对象没有关系
这就是Integer包装器的128陷阱,不知道有多少前辈落入坑中,还是要吸取经验,尽力理解