Java 基础数据类型和包装类的本质区别主要在于以下几个方面:
- 存储位置:基础数据类型存储在栈内存中,而包装类对象存储在堆内存中。
- 值与对象:基础数据类型直接存储的是值,而包装类是对象,封装了对应的基础数据类型的值。
- 默认值:基础数据类型有其自身特定的默认值(如int的默认值为0),而包装类的默认值是null。
- 操作方式:基础数据类型可以直接进行算术运算、比较等操作,而包装类则需要通过方法调用来完成这些操作。
下面让我们通过源码分析更详细地了解这些区别。
基础数据类型
Java 中的八种基础数据类型分别是:
byteshortintlongfloatdoublecharboolean
这些类型在内存中直接存储相应的数值。例如,int 类型的变量直接存储一个32位的整数。
包装类
每种基础数据类型都有一个相应的包装类,这些包装类都位于 java.lang 包中:
ByteShortIntegerLongFloatDoubleCharacterBoolean
以 Integer 类为例,我们通过源码来看看它的实现:
public final class Integer extends Number implements Comparable<Integer> {
private final int value;
public Integer(int value) {
this.value = value;
}
public int intValue() {
return value;
}
// 其他方法,如compareTo, equals, hashCode等
}
从 Integer 类的源码可以看到,它内部包含了一个 int 类型的字段 value,用于存储实际的整数值。包装类不仅仅是将基础数据类型封装成对象,还提供了一些额外的方法,例如 Integer 类中的 parseInt 方法、valueOf 方法等。
自动装箱和拆箱
Java 提供了自动装箱(Autoboxing)和拆箱(Unboxing)的机制,使得基础数据类型和其相应的包装类之间可以自动转换:
int primitiveInt = 5;
Integer wrappedInt = primitiveInt; // 自动装箱
int newPrimitiveInt = wrappedInt; // 自动拆箱
自动装箱源码分析
当执行 Integer wrappedInt = primitiveInt; 时,实际上是调用了 Integer.valueOf 方法:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
这个方法会检查是否在缓存范围内,如果是,则从缓存中返回相应的 Integer 对象,否则创建一个新的 Integer 对象。
自动拆箱源码分析
当执行 int newPrimitiveInt = wrappedInt; 时,实际上是调用了 intValue 方法:
public int intValue() {
return value;
}
这个方法直接返回内部存储的 int 值。
总结
- 基础数据类型:直接存储值,位于栈内存,操作简单高效。
- 包装类:对象形式,存储在堆内存,提供了更多的方法和功能,支持自动装箱和拆箱。