跳至主要內容

Java

LincZero大约 3 分钟

Java

目录

对象包装器与自动装箱

API: java.lang.Integer 1.0 API: java.text.NumberFormat 1.1

包装器(wrapper)

  • 概念

    • 有时,需要将int这样的基本类型转换为对象。所有的基本类型都有一个与之对应的类。 例如,Integer类对应基本类型int。通常,这些类称为包装器
    • 这些对象包装器类拥有很明显的名字: Integer、Long、Float、Double、Short、Byte、(前6个类派生于公共的超类Number) Character、Void和Boolean
  • 特性

    • 对象包装器类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值(除非拆箱再装箱)
    • 对象包装器类还是final,因此不能定义它们的子类
  • 使用场景举例

    • 想定义一个整型数组列表。而尖括号中的类型参数不允许是基本类型。就用到了Integer对象包装器类

      ArrayList<Integer> list = new ArrayList<>();
      
    • 可以将某些基本方法放置在包装器中 例如类型转化的方法

      // 与Integer实例无关,parseInt是一个静态方法
      int x = Integer.parseInt(s);	// 字符串转整型
      

自动装箱(autoboxing)

自动装箱

大家可能认为自动打包(autowrapping)更加合适,而“装箱(boxing)”这个词源自于C#

list.add(3);
// 会自动变为:
list.add(Integer.valueOf(3));

自动拆箱

int n = list.get(i);
// 会自动变成
int n = list.get(i).intValue();

算术表达式中自动拆箱和装箱

Integer n = 3;
n++;	// 自动地插入一条对象拆箱的指令,然后进行自增计算,最后再将结果装箱

类型变化中自动拆箱和装箱

Interger n = 1;
Double x = 2.0;
System.out.println(true?n:x);	// Prints 1.0
								// 如果在一个条件表达式中混合使用Integer和Double类型:
								// Integer值会拆箱,提升为double,再装箱为Double

补充

自动包装器的相等性

基本类型与它们的对象包装器是一样的,只是它们的相等性不同

在两个包装器对象比较时调用equals方法,而不要用==

Integer a = 1000;
Integer b = 1000;
if (a==b) ...		// 结果是不确定的:可能相等也可能不等
    				// 原因:自动装箱规范要求boolean、byte、char≤127,介于-128~127之间的short和int被包装到固定的对象中
    				// 如果a和b初始化为100,则比较结果是成立的
    				// 解决这个问题的办法是在两个包装器对象比较时调用equals方法

包装器引用null

由于包装器类引用可以为null,所以自动装箱有可能会抛出一个NullPointerException异常

Integer n = null;
System.out.println(2*n);	// Throws NullPointerException

依赖编译器而非虚拟机

装箱和拆箱是编译器认可的,而不是虚拟机

如何通过方法修改包装器的数值?通过持有者类型

(这里我也不是很懂)

  • 基本类型值传递,没办法修改值

  • Integer对象不可变,没办法修改值

  • 需要使用在org.omg.CORBA包中定义的持有者(holder)类型:包括IntHolder、BooleanHolder等。 每个持有者类型都包含一个公有域值,通过它可以访问存储在其中的值

    public static void triple(IntHolder x){
        x.value = 3*x.value;
    }