Java基本数据按类型可以分为四大类:布尔型,整数型,浮点型,字符型,这四大类包含8中基本数据类型。
8种基本类型取值如下:
数据类型 | 代表含义 | 默认值 | 取值 | 包装类 |
boolean | 布尔型 | false | 0(false)/1(true) | Boolean |
byte | 字节型 | (byte)0 | -128到127 | Byte |
char | 字符型 | ‘\u0000‘(空) | ‘\u0000‘到‘\uFFFF‘ | Character |
short | 短整数型 | (short)0 | -2^15到2^15 | Short |
int | 整数型 | 0 | -2^31到2^31-1 | Integer |
long | 长整数型 | 0L | -2^63到2^63-1 | Long |
float | 单浮点型 | 0.0f | 1.4e-45到3.4e+38 | Float |
double | 双浮点型 | 0.0d | 4.9e-324到1.798e+308 | Double |
除char的包装类Character和int的包装类Integer之外,其他基本数据类型的包装类只需要首字母大写即可。包装类的作用和特点,本文下半部分详细讲解。
我们可以在代码中,查看某种类型的取值范围,代码如下:
public static void main(String[] args) { // Byte 取值:-128 ~ 127 System.out.println(String.format("Byte 取值: %d ~ %d", Byte.MIN_VALUE,Byte.MAX_VALUE)); // Integer 取值: -2147483648 ~ 2147483647 System.out.println(String.format("Integer 取值: %s ~ %s", Integer.MIN_VALUE,Integer.MAX_VALUE)); }
我们知道8种基本数据类型都有其对应的包装类,因为Java的设计思想是万物既对象,有很多时候我们需要以对象的形式操作器某项功能,比如说获取哈希值(hashcode)或获取类(getClass)等。
那包装类特性有哪些呢?
1.功能丰富
包装类本质上是一个对象,对象就包含属性和方法,比如hashCode、getClass、max、min等。
2.可定义泛型类型参数
包装类可以定义泛型,而基本类型不行。
比如使用Integer定义泛型,代码:
List<Integer> list = new ArrayList<>();
如果使用int定义就会报错,代码:
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 ~ 127 Integer 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一个新的对象。
各包装类高频区域的取值范围:
public static void main(String[] args) { // Integer 高频区缓存范围 -128 ~ 127 Integer 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))); }
-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 =>" + (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之间的数都被缓存了。
原文:https://www.cnblogs.com/Night-Watch/p/11661188.html