JAVA-基础知识-基础数据类型,常量池
基础类型有这样一张表就差不多了
类型 | 包装类 | 默认值 | 最大值 | 最小值 | 长度 | 描述 |
---|---|---|---|---|---|---|
byte | Byte | 0 | 127(2^7-1) | -128(-2^7) | 8 | 有符号的,以二进制补码表示的整数 |
boolean | Boolean | false | 1 | boolean只有两个取值:true 和 false | ||
short | Short | 0 | 32767(2^15-1) | -32768(-2^15) | 16 | 有符号的以二进制补码表示的整数 |
char | Character | ‘\u0000’ | ‘\uffff’ | ‘\u0000’ | 16 | char类型是一个单一的 16 位 Unicode 字符 |
int | Integer | 0 | 2,147,483,647(2^31-1) | -2,147,483,648(-2^31) | 32 | 有符号的以二进制补码表示的整数 |
long | Long | 0L | 9,223,372,036,854,775,807(2^63-1) | -9,223,372,036,854,775,808(-2^63) | 64 | 有符号的以二进制补码表示的整数 |
float | Float | 0.0f | 32 | 单精度、符合IEEE 754标准的浮点数,不能用来表示精确的值,如货币 | ||
double | Double | 0.0d | 64 | 双精度、符合IEEE 754标准的浮点数,不能表示精确的值,如货币 |
自动拆箱和装箱
Java 5增加了自动装箱与自动拆箱机制,方便基本类型与包装类型的相互转换操作。
//在Java 5之前,只能这样做
Integer value = new Integer(10);
//或者这样做
Integer value = Integer.valueOf(10);
//直接赋值是错误的而java5开始,直接赋值是合法的,由编译器来完成转换
Integer value = 10;
实现:
由编译器自动添加转换方法
- 静态方法valueOf(基本类型):将给定的基本类型转换成对应的包装类型;
- 实例方法xxxValue():将具体的包装类型对象转换成基本类型;
有个坑,不知道你以前有没有注意到
/*Integer的构造方法,接受一个整型参数,Integer对象表示的int值,保存在value中*/
public Integer(int value) {
this.value = value;
}
/*equals()方法判断的是:所代表的int型的值是否相等*/
public boolean equals(Object obj) {
if (obj instanceof Integer) {
eturn value == ((Integer)obj).intValue();
}
return false;
}
/*返回这个Integer对象代表的int值,也就是保存在value中的值*/
public int intValue() {
return value;
}
/**
* 首先会判断i是否在[IntegerCache.low,Integer.high]之间
* 如果是,直接返回Integer.cache中相应的元素
* 否则,调用构造方法,创建一个新的Integer对象
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
/**
* 静态内部类,缓存了从[low,high]对应的Integer对象
* low -128这个值不会被改变
* high 默认是127,可以改变,最大不超过:Integer.MAX_VALUE - (-low) -1
* cache 保存从[low,high]对象的Integer对象
*/
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) {
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);
}
high = h;
ache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
在Integer的源码里面有这样一段,通过分析
- Integer有一个实例域value,它保存了这个Integer所代表的int型的值,且它是final的,也就是说这个Integer对象一经构造完成,它所代表的值就不能再被改变。
- Integer重写了equals()方法,它通过比较两个Integer对象的value,来判断是否相等。
- 重点是静态内部类IntegerCache,通过类名就可以发现:它是用来缓存数据的。它有一个数组,里面保存的是连续的Integer对象。
- low:代表缓存数据中最小的值,固定是-128。
- high:代表缓存数据中最大的值,它可以被该改变,默认是127。high最小是127,最大是Integer.MAXVALUE-(-low)-1,如果high超过了这个值,那么cache[ ]的长度就超过Integer.MAXVALUE了,也就溢出了。
- cache[]:里面保存着从[low,high]所对应的Integer对象,长度是high-low+1(因为有元素0,所以要加1)。
- 调用valueOf(int i)方法时,首先判断i是否在[low,high]之间,如果是,则复用Integer.cache[i-low]。比如,如果Integer.valueOf(3),直接返回Integer.cache[131];如果i不在这个范围,则调用构造方法,构造出一个新的Integer对象。
- 调用intValue(),直接返回value的值。通过3和4可以发现,默认情况下,在使用自动装箱时,VM会复用[-128,127]之间的Integer对象。
然后可以试试这个:
public static void main(String[] args) {
//基本数据类型的常量池是-128到127之间。
// 在这个范围中的基本数据类的包装类可以自动拆箱,比较时直接比较数值大小。
//int的自动拆箱和装箱只在-128到127范围中进行,超过该范围的两个integer的 == 判断是会返回false的。
Integer a1 = 128;
Integer a2 = 128;
Integer a3 = -128;
Integer a4 = -128;
System.out.println(a1 == a2); //false
System.out.println(a3 == a4); //true
Byte b1 = 127;
Byte b2 = 127;
Byte b3 = -128;
Byte b4 = -128;
//byte都是相等的,因为范围就在-128到127之间
System.out.println(b1 == b2); //true
System.out.println(b3 == b4); //true
Long c1 = 128L;
Long c2 = 128L;
Long c3 = -128L;
Long c4 = -128L;
System.out.println(c1 == c2); //false
System.out.println(c3 == c4); //true
//char没有负值
//发现char也是在0到127之间自动拆箱
Character d1 = 128;
Character d2 = 128;
Character d3 = 127;
Character d4 = 127;
System.out.println(d1 == d2); //false
System.out.println(d3 == d4); //true
}
- Integer默认复用了[-128,127]这些对象,其中高位置可以修改;
- Byte复用了全部256个对象[-128,127];
- Short服用了[-128,127]这些对象;
- Long服用了[-128,127];
- Character复用了[0,127],Charater不能表示负数;
- Double和Float是连续不可数的,所以没法复用对象,也就不存在自动装箱复用陷阱。
- Boolean没有自动装箱与拆箱,它也复用了Boolean.TRUE和Boolean.FALSE,通过Boolean.valueOf(boolean b)返回的Blooean对象要么是TRUE,要么是FALSE,这点也要注意。