一文彻底搞懂:Java基本数据类型详解
Java 基本数据按类型可以分为四大类:布尔型、整数型、浮点型、字符型,这四大类包含 8 种基本数据类型。
• 布尔型: boolean
• 整数型: byte 、 short 、 int 、 long
• 浮点型: float 、 double
• 字符型: char
8 种基本类型取值如下:

除 char 的包装类 Character 和 int 的包装类 Integer 之外,其他基本数据类型的包装类只需要首字母大写即可。包装类的作用和特点,本文下半部分详细讲解。
我们可以在代码中,查看某种类型的取值范围,代码如下:
public static void main(String[] args) {// Byte 取值:-128 ~ 127System.out.println(String.format("Byte 取值:%d ~ %d", Byte.MIN_VALUE, Byte.
MAX_VALUE));// Int 取值:-2147483648 ~ 2147483647System.out.println(String.format("Int 取值:%d ~ %d", Integer.MIN_VALUE, Int
eger.MAX_VALUE));
}
包装类型
我们知道 8 种基本数据类型都有其对应的包装类,因为 Java 的设计思想是万物既对象,有很多时候我们需要以对象的形式操作某项功能,比如说获取哈希值(hashCode )或获取类( getClass )等。
那包装类特性有哪些?
1. 功能丰富
包装类本质上是一个对象,对象就包含有属性和方法,比如 hashCode 、
getClass 、 max 、 min 等。
2. 可定义泛型类型参数
包装类可以定义泛型,而基本类型不行。
比如使用 Integer 定义泛型,代码:
List <Integer> list = new ArrayList<>();
如果使用 int 定义就会报错,代码:
List list = new ArrayList<>(); // 编译器代码报错
3. 序列化
因为包装类都实现了 Serializable 接口,所以包装类天然支持序列化和反序列化。
比如 Integer 的类图如下:

4. 类型转换
包装类提供了类型转换的方法,可以很方便的实现类型之间的转换,比如 Integer 类型转换代码:
String age = "18" ;
int ageInt = Integer.parseInt(age) + 2 ; // 输出结果: 20
System. out .println(ageInt);
5. 高频区间的数据缓存
此特性为包装类很重要的用途之一,用于高频区间的数据缓存,以 Integer 为例来说,在数值区间为 -128~127 时,会直接复用已有对象,在这区间之外的数字才会在堆上产生。
我们使用 == 对 Integer 进行验证,代码如下:
public static void main(String[] args) {// Integer 高频区缓存范围 -128~127Integer num1 = 127;Integer num2 = 127;// Integer 取值 127 == 结果为 true(值 127 num1==num2 => true)System.out.println("值 127 num1==num2 => " + (num1 == num2));Integer num3 = 128;Integer num4 = 128;// Integer 取值 128 == 结果为 false(值 128 num3==num4 => false)System.out.println("值 128 num3==num4 => " + (num3 == num4));
}
从上面的代码很明显可以看出, Integer 为 127 时复用了已有对象,当值为 128 时,重新在堆上生成了新对象。
为什么会产生高频区域数据缓存?我们查看源码就能发现 “ 线索 ” ,源码版本 JDK8,源码如下:
public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
}
由此可见,高频区域的数值会直接使用已有对象,非高频区域的数值会重新 new
一个新的对象。
各包装类高频区域的取值范围:
• Boolean :使用静态 final 定义,就会返回静态值
• Byte :缓存区 -128~127
• Short :缓存区 -128~127
• Character :缓存区 0~127
• Long :缓存区 -128~127
• Integer :缓存区 -128~127
包装类的注意事项
• int 的默认值是 0 ,而 Integer 的默认值是 null 。
• 推荐所有包装类对象之间的值比较使用 equals() 方法,因为包装类的非高频区数据会在堆上产生,而高频区又会复用已有对象,这样会导致同样的代码,因为取值的不同,而产生两种截然不同的结果。
代码示例:
public static void main(String[] args) {// Integer 高频区缓存范围 -128~127Integer num1 = 127;Integer num2 = 127; // Integer 取值 127 == 结果为 true(值 127 num1==num2 => true)System.out.println("值 127 num1==num2 => " + (num1 == num2));Integer num3 = 128;Integer num4 = 128;// Integer 取值 128 == 结果为 false(值 128 num3==num4 => false)System.out.println("值 128 num3==num4 => " + (num3 == num4));// Integer 取值 128 equals 结果为 true(值 128 num3.equals(num4) => true)System.out.println("值 128 num3.equals(num4) => " + num3.equals(num4));
}
• Float 和 Double 不会有缓存,其他包装类都有缓存。
• Integer 是唯一一个可以修改缓存范围的包装类,在 VM optons 加入参
数:
-XX:AutoBoxCacheMax=666 即修改缓存最大值为 666 。
示例代码如下:
public static void main(String[] args) {Integer num1 = -128;Integer num2 = -128;System.out.println("值为-128 => " + (num1 == num2));Integer num3 = 666;Integer num4 = 666;System.out.println("值为 666 => " + (num3 == num4));Integer num5 = 667;Integer num6 = 667; System.out.println("值为 667 => " + (num5 == num6));
}
执行结果如下:
值为 -128 => true
值为 666 => true
值为 667 => false
由此可见将 Integer 最大缓存修改为 666 之后, 667 不会被缓存,而 -128~666
之间的数都被缓存了。
