Java 的自动装箱拆箱

时间:2023-03-09 04:11:19
Java 的自动装箱拆箱

Java 是面向对象的语言,其基本数据类型也就有了相对应的类,称为包装类。以下是基本数据类型对应的包装类:

基本数据类型

包装类

byte(1字节)

Byte

short(2字节)

Short

int(4字节)

Integer

long(8字节)

Long

float(4字节)

Float

double(8字节)

Double

char(2字节)

Character

boolean(1/8字节)

Boolean

自动装箱、拆箱:

在 jdk1.5 以前,创建 Integer 对象需要调用其构造方法:

Integer i = new Integer(5);

jdk1.5 具有自动装箱拆箱功能:

Integer i = 5;  //装箱
int j = i; //拆箱

其原理是调用了 Integer 的 valueOf(int) 和 Integer 对象的 intValue() 方法:

public static void intTest() {
Integer integer = 2;
int i = integer;
System.out.println(i);
}
//反编译后
public static void intTest() {
Integer integer = Integer.valueOf(2);
int i = integer.intValue();
System.out.println(i);
}

IntegerCache 类:

IntegerCache 是 Integer 类中一个私有的静态类,用于整型对象的缓存。

Integer i1 = 2;
Integer i2 = 2; System.out.println(i1 == i2); //true

该缓存策略仅在自动装箱时适用,也就是使用 new Integer() 的方式构建的 Integer 对象!=:

Integer i1 = new Integer(2);
Integer i2 = new Integer(2); System.out.println(i1 == i2); //false

并且只适用于整数区间 -128 到 +127:

Integer i1 = 300;
Integer i2 = 300; System.out.println(i1 == i2); //false

源码里 Integer 的 valueOf(int) 方法:

public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
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() {}
}

源码里规定了缓存的范围最小为:-128 到 +127 ,最大值映射到 java.lang.Integer.IntegerCache.high,可以使用 JVM 的启动参数 -XX:AutoBoxCacheMax=size 设置最大值。

其他包装类:

Byte,Short,Long,Character 也有相应的缓存类;

Byte,Short,Long 有固定范围: -128 到 127。对于 Character, 范围是 0 到 127;

另外,只有 Integer 可以通过参数改变范围。

boolean:

        Boolean b1 = false;
Boolean b2 = false;
Boolean b3 = true;
Boolean b4 = true; System.out.println(b1==b2); //true
System.out.println(b3==b4); //true

Integer 与 Long:

        Integer a = 1;
Integer b = 2;
Long g = 3L;
Long h = 2L; System.out.println(g==(a+b)); //true
System.out.println(g.equals(a+b)); //false
System.out.println(g.equals(a+h)); //ture

"==" 与 equals :

1,”==“可以用于原始值进行比较,也可以用于对象进行比较,当用于对象与对象之间比较时,比较的不是对象代表的值,而是检查两个对象是否是同一对象,这个比较过程中没有自动装箱发生。

2,进行对象值比较不应该使用”==“,而应该使用对象对应的 equals 方法。

3,equals 方法是 Object 类的一个方法:

     public boolean equals(Object obj) {
return (this == obj);
}

许多类会重写这个方法:

① Integer 类重载了该方法:

     public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
     Integer i1 = 300;
Integer i2 = 300; System.out.println(i1 == i2); //false 两个不同的地址引用
System.out.println(i1.equals(i2)); //true 两个相同的值(变为两个 int 之间的比较,所以比较值)

② String 重载了该方法:当两值不 == 时,比较他们的值

     public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}

所以,当对象没有重写 equals 时,== 与 equals 是等价的。

另外:

        Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2); int[] id = new int[9];

//数组下就不能这么装了...
//int[] ints = set.toArray(new Integer[0]);
Integer[] integers = set.toArray(new Integer[0]); for(int i=0;i<=set.size()-1;i++){
id[i] = set.toArray(new Integer[0])[i];
}