题记:当研究完之后突然发现自己用了这么久的Integer和int居然连这点都不知道,记录一下自己的成长。
一、总结一下Java的基本类型和引用类型
特点总结:
1》引用数据类型的大小统一为4个字节,记录的是其引用对象的地址!
字节:字节(Byte )是计算机信息技术用于计量存储容量的一种计量单位,作为一个单位来处理的一个二进制数字串,是构成信息的一个小单位。最常用的字节是八位的字节,即它包含八位的二进制数。1和0是计算机储存的基本单位,包括现在电脑上看到的所有一切都是由1和0两个数组成的,一个即是一个位,8位(bit)一个字节,我们在电脑中看到的图像视频等都是计算机通过对储存器中无数个1和0的计算得来的。
2》基本数据类型
一个字节等于8位:1byte=8bit.
数据类型 | 字节 | 字节大小(位) | 封装类型 | 取值范围 |
byte | 1byte | 8bit | Byte | 最小值是 -128(-2^7); 最大值是 127(2^7-1); |
short | 2byte | 16bit | Short | 最小值是 -32768(-2^15); 最大值是 32767(2^15 - 1); |
int | 4byte | 32bit | Integer | 最小值是 -2,147,483,648(-2^31); 最大值是 2,147,483,647(2^31 - 1); |
long | 8byte | 64bit | Long | 最小值是 -9,223,372,036,854,775,808(-2^63); 最大值是 9,223,372,036,854,775,807(2^63 -1); |
float | 4byte | 32bit | Float | 单精度浮点数字长32位,尾数长度23,指数长度8,指数偏移量127; -3.403E38~3.403E38 |
double | 8byte | 64bit | Doble | 双精度浮点数字长64位,尾数长度52,指数长度11,指数偏移量1023; -1.798E308~1.798E308 |
char | 2byte | 16bit | Character | 最小值:Character.MIN_LOW_SURROGATE 最大值:Character.MAX_HIGH_SURROGATE |
boolean | 1byte | Boolean | true,false |
十进制整数,如:99, -500, 0 3》Java 语言整型常量的四种表示形式
-
八进制整数,要求以 0 开头,如:015
-
十六进制数,要求 0x 或 0X 开头,如:0x15
-
二进制数,要求0b或0B开头,如:0b01110011
二、拆箱,装箱
简单来说:
自动装箱就是自动将基本数据类型转换为包装器类型;
自动拆箱就是自动将包装器类型转换为基本数据类型。
三、int和Integer的区别
1、Integer是int的包装类,int则是java的一种基本数据类型
2、Integer变量必须实例化后才能使用,而int变量不需要
3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
4、Integer的默认值是null,int的默认值是0
四、代码比较
1,new两个Integer进行比较
@Test
public void test2(){
Integer aa=new Integer(1);
Integer bb=new Integer(1);
System.out.println(aa==bb);//false
System.out.println(aa.equals(bb));//true
}
总结:这里不用多说,aa==bb比较的堆内存中的地址,因为new了两个对象所以为false。
aa.equals(bb)比较的是文本内容所以未ture。
2,new一个Integer和一个int类型的比较
@Test
public void test2(){
Integer aa=new Integer(1);
int bb=1;
System.out.println(aa==bb);//true
System.out.println(aa.equals(bb));//true
}
总结:按照常理一个是堆内存中的一个是常量池的,肯定是false,true才对啊,为什么是true,true。原因:因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较)
3,new一个Integer,直接赋值一个Integer
@Test
public void test2(){
Integer aa=new Integer(1);
Integer bb=1;
System.out.println(aa==bb);//false
System.out.println(aa.equals(bb));//true
}
总结:因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同
4,两个Integer直接赋值
@Test
public void test2(){
Integer aa=1;
Integer bb=1;
System.out.println(aa==bb);//true
System.out.println(aa.equals(bb));//true
}
总结:这里不难理解,全部指向常量池中,所以全是true。
但是当值大于127时看下边代码
@Test
public void test2(){
Integer aa=128;
Integer bb=128;
System.out.println(aa==bb);//false
System.out.println(aa.equals(bb));//true
}
总结:是不是膛目结舌,不由自主的一句WC,原因得从源码说起:看一下Integer的源码
static final int low = -128;
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() {}
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
当i大于等于最小值-128并且小于等于最大值127时,会调用IntegerCache.cache(),进行缓存,所以第一个两个true是因为第一次添加到了缓存中,第二次获取的也是缓存中的数值。所以打印了两个true。
当大于127时,代码底层实际上是new 了两个Integer所以其实是再对内存中存在两个不同的对象。