Java包装类:128陷阱与自动拆装箱

在Java的世界中,包装类是一个不可或缺的存在。它们为基本数据类型提供了对象化的支持,使得基本类型能够参与到面向对象的编程范式中。然而,包装类的使用并非总是那么简单,尤其是当涉及到“128陷阱”和自动拆装箱时,稍有不慎便可能引发意想不到的问题。本文将带你深入探讨Java包装类的奥秘,揭示其中的陷阱与技巧。

一、为什么有包装类

Java作为一门面向对象的编程语言,其核心思想是“一切皆对象”。然而,基本数据类型(如intcharboolean等)却并非对象,这在一定程度上限制了Java的纯粹性。为了解决这一问题,Java引入了包装类,将基本数据类型封装成对象,从而使其能够参与到对象的操作中。

Java为每种基本数据类型都提供了对应的包装类:

  • int------>Integer*
  • char------>Character*
  • byte------>Byte
  • short------>Short
  • long------>Long
  • float------>Float
  • double------>Double
  • boolean------>Boolean

二、自动拆装箱

自动装箱是指将基本数据类型自动转换为对应的包装类对象,而自动拆箱则是将包装类对象自动转换为基本数据类型。

举个例子:

Integer a1 = 100;// 会被编译成:Integer.valueOf(100) 是自动装箱
int a2 = a1; //会被编译成:int a2 = a1.intValue()是自动拆箱

简单来说int类型转换Integer就是装箱,Integer类型转换为int就是拆箱。

自动拆装箱虽然带来了极大的便捷但也产生了一些潜在的问题,尤其是“128陷阱”。

三、“128陷阱”

在Java中,Integer类内部维护了一个缓存池,默认情况下会缓存-128127之间的Integer对象。这意味着,在Integer的valueOf()方当中,我们将数值在-128-127之间的数值都存储在有一个catch数组当中,该数组相当于一个缓存,当我们定义的数据在[-128,127],程序直接返回该值在数组当中的地址,所以在-128-127之间的数值用==进行比较是相等的。而不在这个区间的数,需要新开辟一个内存空间,所以不相等。
举个例子:

Integer a1 = 100;
Integer a2 = 100;
System.out.println(a1 == a2);  //true

当执行Integer  a1 =100;时,Java会进行自动装箱操作,将基本数据类型int转换为Integer对象;由于100在-128到127的范围内,Java会从Integer的缓存池中直接返回一个已经存在的Integer对象,而不是创建一个新的对象,同理,Integer a2=100;也会从缓存池中返回同一个Integer对象。因此,a1和a2的引用是相同的,所以返回true。

内存图如下:

Java包装类:128陷阱与自动拆装箱_第1张图片

但如果超出缓存范围

 Integer a3 = 200;
 Integer a4 = 200;
 System.out.println(a3 == a4); //false

由于128超出了-128到127的缓存范围,Java会为a3和a4分别创建新的Integer对象,因此a3和a4指向的是两个不同的对象,==比较的结果为false。

内存图如下:

Java包装类:128陷阱与自动拆装箱_第2张图片


四、习题练习

int  a = 10;
int  b = 10;
Integer a1 = 10;
Integer b1 = 10;
Integer a2 = new Integer(10);
Integer b2 = new Integer(10);

System.out.println(a == b);         
System.out.println(a1 == b1);       
System.out.println(a2 == b2);      
System.out.println(a1 == a);  
System.out.println(a1.equals(a));
System.out.println(a1 == a2); 
System.out.println(a == a2);  
  • 第一个返回true 因为a和b都是基本数据类型;
  • 第二个返回true,因为a1和b1都在范围内,它们指向的引用相同;
  • 第三个返回false,因为a2和b2分别创建了一个新的对象;
  • 第四个返回true,会自动拆箱,a1是Integer类型的 a是int类型的, 判断时候Integer要转出int来判断。
  • 第五个返回true,原理同上,equals()的底层还是==。
  • 第六个返回返回false,a1的值10是从catch缓存池数据当中获取的  a2的值10是自己创建创建的对象。
  • 第七个返回true,会自动拆箱,a2是Integer类型的 a是int类型的, 判断时候Integer要转出int来判断。

你可能感兴趣的:(java,开发语言)