Java-数据类型

leard 发布于 2024-05-16 0 次阅读


8种基本数据类型

  • 6 种数字类型 :byte、short、int、long、float、double
  • 1 种字符类型:char
  • 1 种布尔型:boolean
基本类型位数字节默认值
int3240
short1620
long6480L
byte810
char162'u0000'
float3240f
double6480d
boolean1false

Java 里使用 long 类型的数据一定要在数值后面加上 L,否则将作为整型解析

char a = 'h',char:单引号;String a = "hello",String:双引号

包装类型

八种基本类型都有对应的包装类分别为:Byte、Short、Integer、Long、Float、Double、Character、Boolean

基本类型和包装类型的区别

  • 用途:除了定义一些常量和局部变量之外,我们在其他地方比如方法参数、对象属性中很少会使用基本类型来定义变量。并且,包装类型可用于泛型,而基本类型不可以。
  • 存储方式:基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中,基本数据类型的成员变量(未被 static 修饰 )存放在 Java 虚拟机的堆中。包装类型属于对象类型,我们知道几乎所有对象实例都存在于堆中。
  • 占用空间:相比于包装类型(对象类型), 基本数据类型占用的空间往往非常小。
  • 默认值:成员变量包装类型不赋值就是 null ,而基本类型有默认值且不是 null。
  • 比较方式:对于基本数据类型来说,== 比较的是值。对于包装数据类型来说,== 比较的是对象的内存地址。所有整型包装类对象之间值的比较,全部使用 equals() 方法。

为什么几乎所有对象实例都存在于堆中?

这是因为 HotSpot 虚拟机引入了 JIT 优化之后,会对对象进行逃逸分析,如果发现某一个对象并没有逃逸到方法外部,那么就可能通过标量替换来实现栈上分配,而避免堆上分配内存。基本数据类型存放在栈中是一个常见的误区! 基本数据类型的成员变量如果没有被 static 修饰的话(不建议这么使用,应该要使用基本数据类型对应的包装类型),就存放在堆中。

包装类型的常量池技术

  • Byte、Short、Integer、Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据
  • Character 创建了数值在[0,127]范围的缓存数据
  • Boolean 直接返回 True Or False
  • Float、Double 并没有实现常量池技术

如果超出对应范围仍然会去创建新的对象,缓存的范围区间的大小只是在性能和资源之间的权衡。

Integer i1=40;
Integer i2 = new Integer(40);

Integer i1=40 这一行代码会发生装箱,也就是说这行代码等价于 Integer i1=Integer.valueOf(40) 。因此,i1 直接使用的是常量池中的对象。而Integer i2 = new Integer(40) 会直接创建新的对象。

为什么要有包装类型

Java 本身就是一门 OOP(面向对象编程)语言,对象可以说是 Java 的灵魂。假如一个对象中的属性使用了基本类型,那这个属性就必然存在默认值了。这个逻辑不正确的!因为很多业务场景下,对象的某些属性没有赋值,就是希望它的值为 null。默认赋个值的话,属于是帮倒忙。

另外,像泛型参数不能是基本类型。因为基本类型不是 Object 子类,应该用基本类型对应的包装类型代替。

自动拆装箱

基本类型和包装类型之间的互转。

Integer i1 = 40;//装箱
int i2 = i1;//拆箱

装箱其实就是调用了 包装类的valueOf()方法,拆箱其实就是调用了 xxxValue()方法。

Integer i = 10; //等价于 Integer i = Integer.valueOf(10);
int n = i; //等价于 int n = i.intValue();

自动拆箱引发的 NPE(空指针)问题

数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险,三目运算符使用不当也会导致诡异的 NPE 异常。

public class Main { 
    public static void main(String[] args) { 
        Integer i = null; 
        Boolean flag = false; 
        System.out.println(flag ? 0 : i); 
    }
}

flag ? 0 : i 这行代码中,0 是基本数据类型 int,返回数据的时候 i 会被强制拆箱成 int 类型,由于 i 的值是 null,因此就抛出了 NPE 异常。

把代码中 flag 变量的值修改为 true 的话,就不会存在 NPE 问题了,因为会直接返回 0,不会进行拆箱操作。