基本数据类型
Java提供了9种基本数据类型,他们都不具备对象的特性,没有属性和行为。基本数据类型是指不可再分的原子数据类型,内存中直接存储此类型的值,通过内存地址即可直接访问到数据,并且此内存区域只能存放这种类型的值。
Java的9种基本数据类型包括boolean、byte、char、short、int、long、float、double和refvar。前8种数据类型表示生活中的真假、字符、整数和小树,最后一种refvar是面向对象世界中的引用变量,也叫引用句柄。
下表展示了8种基本数据类型的默认值、空间占用大小、表示范围及对应的包装类等信息:
序号 | 类型名称 | 默认值 | 大小 | 最小值 | 最大值 | 包装类 | 缓存区间 |
1 | boolean | FALSE | 1B | 0(false) | 1(true) | Boolean | 无 |
2 | byte | (byte)0 | 1B | -128 | 127 | Byte | -128~127 |
3 | char | \u0000' | 2B | \u0000' | \uFFFF' | Character | (char)0~(char)127 |
4 | short | (short)0 | 2B | -2^15 | (2^15)-1(32767) | Short | -128~127 |
5 | int | 0 | 4B | -2^31 | (2^31)-1 | Integer | -128~127 |
6 | long | 0L | 8B | -2^63 | (2^63)-1 | Long | -128~127 |
7 | float | 0.0f | 4B | 1.4e-45 | 3.4e+38 | Float | 无 |
8 | double | 0.0d | 8B | 4.9e-324 | 1.798e+308 | Double | 无 |
包装类型
Java前8种基本数据类型都有相应的包装类,因为Java的设计理念是一切皆是对象,在很多情况下,需要以对象的形式操作,比如hashCode()获取哈希值,或者getClass()获取类等。
包装类的存在解决了基本数据类型无法做到的事情:泛型类型参数、序列化、类型转换、高频区间数据缓存。
从上表及源码可知,Integer会缓存-128~127 之间的值,对于Integer var = ?在-128~127之间的赋值,Integer对象由IntegerCache.cahce产生,会复用已有对象,这个区间内的Integer值可以直接使==进行判断,但是这个区间之外的所有数据都会在堆上产生,并不会复用已有对象,这是一个大问题。因此,推荐所有包装类对象之间值的比较,全部使用equals()方法。
事实上,除Float和Double之外,其他包装数据类型都会缓存,6个包装类直接赋值时,就是调用对应包装类的静态工厂方法valueOf()。
在JDK9直接把new的构造方法过时,推荐使用valueOf(),合理利用缓存,提升程序性能。各个包装类的缓存区间如下:
- Boolean:使用静态final变量定义,valueOf()就是返回这两个静态值;
- Byte:表示范围是-128~127,全部缓存;
- Short:表示范围是-32768~32767,缓存范围是-128~127;
- Character:表示范围是0~655335,缓存范围是0~127;
- Long:表示范围是[-2^63,(2^63)-1],缓存范围是-128~127;
- Integer:表示范围是[-2^31,(2^31)-1],缓存范围是-128~127.
Integer是Java数据世界里应用最广的数据类型,缓存区间为-128~127。
他是唯一可以修改缓存范围的包装类,在VM Options加入参数-XX:AutoBoxCacheMax=8888,即可设置最大缓存值为8888,
示例代码如下:
package com.htzw.study;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class LongIntegerCacheTest {
public static void main(String[] args){
Long a = 127L;
Long b = 127L;
log.info("Long max cached value is 127,and the result is :"+(a == b));
Long a1 = 128L;
Long b1 = 128L;
log.info("Long =128 cache is :"+(a1 == b1));
Long c= -128L;
Long d = -128L;
log.info("Long min cached value is -128,and the result is :"+(c == d));
Long c1= -129L;
Long d1 = -129L;
log.info("Long = -129 cached is :"+(c1 == d1));
// Long类型只缓存-128~127之间的数据
Long e = 1000L;
Long f = 1000L;
log.info("Long = 1000 cached is :"+(e == f));
// JVM AutoBoxCacheMax只对Integer对象有效
Integer x = 1001;
Integer y = 1001;
log.info("Integer = 1001 is {}",(x == y));
}
}
执行结果如下所示:
22:39:48.339 [main] INFO com.htzw.study.LongIntegerCacheTest - Long max cached value is 127,and the result is :true
22:39:48.339 [main] INFO com.htzw.study.LongIntegerCacheTest - Long =128 cache is :false
22:39:48.339 [main] INFO com.htzw.study.LongIntegerCacheTest - Long min cached value is -128,and the result is :true
22:39:48.339 [main] INFO com.htzw.study.LongIntegerCacheTest - Long = -129 cached is :false
22:39:48.339 [main] INFO com.htzw.study.LongIntegerCacheTest - Long = 1000 cached is :false
22:39:48.354 [main] INFO com.htzw.study.LongIntegerCacheTest - Integer = 1001 is true
该例说明了Long只是缓存了-128~127之间的数值,而1000L没有被缓存,在将Integer最大缓存值改为8888后,1001被成功缓存。
在选择使用包装类还是基本数据类型,推荐使用如下方式:
(1)所有的POJO类属性必须使用包装数据类型 ;
(2)RPC方法的返回值和参数必须使用包装数据类型;
(3)所有的局部变量推荐使用基本数据类型。