为什么会需要包装类型
我们知道Java是一个面相对象的编程语言,基本类型并不具有对象的性质,为了让基本类型也具有对象的特征,就出现了包装类型(如我们在使用集合类型Collection时就一定要使用包装类型而非基本类型),它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,丰富了基本类型的操作。
当需要往ArrayList,HashMap中放东西时,像int,double这种基本类型是放不进去的,因为容器都是装object的,这是就需要这些基本类型的包装器类了。
Java的基本类型(元数据)与对应的包装类型:
基本类型 | 基本类型大小 | 包装类型 |
---|---|---|
byte | 1个字节 | Byte |
shot | 2个字节 | Short |
int | 4个字节 | Integer |
long | 8个字节 | Long |
float | 4个字节 | Float |
double | 8个字节 | Double |
char | 取决于底层保存的字符 | Character |
boolean | Boolean |
包装类的缺点:
在 64 位的 Java 虚拟机中,每一个 Java 对象在内存中的额外开销就最少是16 个字节。以 Integer 类为例,它仅有一个 int 类型的私有字段,占 4 个字节。因此,每一个 Integer 对象的额外内存开销至少是int的400%
什么是自动装箱和拆箱
自动装箱:将基本的类型数据转换为对应的包装包装类型数据
Integer a = 1;//装箱
自动拆箱:将包装类型转换为基本类型数据
int b = a; //拆箱
自动拆箱和装箱的实现
下面是很简单的自动装箱与自动拆箱的代码,进过反编译结果在下图:
当进行自动装箱时代用的是valueOf()方法
当进行自动拆箱时,代用的是intValue()方法
IntegerCahe分析
IntegerCache的详细可以看:https://blog.csdn.net/zx6571269/article/details/82026879 这篇文章是转载的个人感觉写的非常好
Integer里面只有一个value属性.
swap主要用于交换两个Integer对象在栈里面的数据。
private static void swap(Integer a,Integer b) throws NoSuchFieldException, IllegalAccessException {
Field valueField = Integer.class.getDeclaredField("value");
valueField.setAccessible(true);
int temp = valueField.getInt(a);
valueField.setInt(a,b.intValue());
valueField.setInt(b,temp);
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Integer a=1,b=2;
swap(a,b);
System.out.println("a=:"+a);
System.out.println("b=:"+b);
Integer c=1;
System.out.println("c=:"+c);
System.out.println("b=:"+b);
}
大家可以猜猜结果:
IntegerCache实现
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
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;
//查找JVM,Integer初始化的缓存设置
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是一个静态的内部类,当,第一次初始化化是,,int c = 1
反编译后的Integer c = Integer.valueOf((int)1);
其中java.lang.Integer.IntegerCache.high的取值范围,它默认的范围是[-128,127]之间。在该区间内所有的Integer.valueOf(int)
函数返回的对象,是根据int值计算的偏移量,从数组Integer.IntegerCache.cache
中获取,对象是同一个,不会新建对象。所以当我们修改了Integer.valueOf(1)的value后,所有Integer.IntegerCache.cache[ 1 - IntegerCache.low ]
的返回值都会变更。
包装类 | 是否有Cache | 范围 |
---|---|---|
Byte | ByteCache | [-128,127](固定) |
Short | ShortCache | [-128,127](固定) |
int | IntegerCache | [-128,Integer.MAX_VALUE - (-low) -1] |
long | LongCache | [-128,127](固定) |
float | – | – |
Double | – | – |
Character | CharacterCache | [0,127] |
Boolean | – | – |
参考1:https://www.jb51.net/article/129640.htm
参考2:https://www.cnblogs.com/dolphin0520/p/3780005.html
参考3:https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html