前言
从开始接触Java到现在也有两年的时间了,还记得最开始就是学数据类型,这是最基础的,可能大家会觉得这没有什么好讲的,但是很多时候我们在开发中可能会忽略关于它们的一些知识点,这篇文章将给大家带来关于Java基本类型与对应的包装类型。
基本类型
以下通过一个表格来说明它们:
类型 | 字节数 | 取值范围 |
---|---|---|
byte | 1 | -2^7 ~ 2^7 - 1 |
short | 2 | -2^15 ~ 2^15 - 1 |
char | 2 | 0 ~ 2^16 - 1 |
int | 4 | -2^31 ~ 2^31 - 1 |
float | 4 | 1.4E - 45 ~ 3.4028235E38 |
long | 8 | -2^63 ~ 2^63 - 1 |
double | 8 | 4.9E - 324 ~ 1.7976931348623157E308 |
以上有必要讲一下long和double,由于它们两个都是8位字节,也就相当于64位,所以在JVM中的局部变量表中,它们的存放需要两个变量空间(Slot),所以它们并没具有原子性,所以在使用它们的时候要注意线程安全问题,可用volatile进行修饰,以保证原子性操作。
包装类
以上的基本类型,它们分别都对应着一个包装类:
Byte、Short、Character、Integer、Float、Long、Double。
在最开始的时候,我很好奇为什么有了基本类型,还要它们的包装类型。其实就是把对应的类型的功能变得强大,而且在某些操作之间变得很方便,就比如与String之间的转换:
int i=Integer.valueOf("-88");
long l=Long.parseLong("800");
而如果是基本类型则显得很无力。
包装类与基本类型之间的区别
- 包装类需要new关键字区创建,也就是指向的是地址值。
- 基本类型并非是引用,它们直接指向的是赋予的值。
- 包装类是对象,拥有方法和字段,而基本类型没有。
- 存储位置不同,基本类型数据直接将值保存在值栈中,包装类型把对象放在堆中,通过引用去操作它。
装箱与拆箱
装箱:
Long t1 = 1000L;
系统将以上的语句编译成:
Long t1 = Long.valueOf(1000L);
拆箱:
Long l1=100L;
long l2=l1;
使用包装类型的注意点
先看个例子
Integer i1=new Integer(100);
Integer i2=new Integer(100);
System.out.println("i1==i2::"+(i1==i2));
Integer ii1=127;
Integer ii2=127;
System.out.println("ii1==ii2::"+(ii1==ii2));
Integer iii1=128;
Integer iii2=128;
System.out.println("iii1==iii2::"+(iii1==iii2));
输出结果:
i1==i2::false
ii1==ii2::true
iii1==iii2::false
相信有人可能会觉得很奇怪为什么iii1==iii2的结果为false,这涉及到了JVM的知识,在JVM维护了八种基本类型的常量池,int常量池中初始化为-128~127,所以当Integer i=127时,在自动装箱的过程中是取自常量池中的数值,而当Integer 1=128时,128不在常量池中,所以在自动装箱过程中会new一个出来,所以地址就不一样了,由于“==”比较的是地址值,所以导致最终结果为false。
总结
- 如果使用效果相同,尽量使用基本类型。因为效率高,性能好。
- 如果把握不住数值的范围,则拆箱为基本类型,防止比较的时候会与预想的不同
- 如果使用long、double时,需要的时候用volatile修饰,保证安全。
以上便是基本类型与包装类型的介绍,希望大家喜欢。