JavaRush /Java 博客 /Random-ZH /Java 中的自动装箱和拆箱
DSergey_Kh
第 12 级

Java 中的自动装箱和拆箱

已在 Random-ZH 群组中发布
在本文中,我们将了解 Java 中称为自动装箱/拆箱的功能。自动装箱和拆箱是将原始类型转换为对象类型的功能,反之亦然。 Java 中的自动装箱和拆箱 - 1整个过程由Java运行时环境(JRE)自动执行。但在实现这个功能时你应该小心,因为...... 它会影响程序的性能。

介绍

int在 JDK 1.5 以下的版本中,将、charfloat、 等原始数据类型转换double为它们的包装类 Integer、Character、Float、Double并不容易。从 JDK 5 开始,自动实现将原始类型转换为等效对象的功能。此属性称为自动装箱。相反的过程分别是拆箱,即 将对象转换为其相应的原始类型的过程。自动装箱和拆箱的示例代码如下:
Integer integer = 9;
拆箱
int in = 0;
in = new Integer(9);
什么时候使用自动装箱和拆箱? Java 编译器在以下条件下使用自动装箱:
  • 当基本类型的值作为方法参数传递给方法时,需要相应包装类的对象。
  • 当将原始类型的值分配给相应包装类的变量时。
考虑以下示例: 清单 1:显示自动装箱的简单代码
public int sumEvenNumbers(List<Integer> intList ) {
int sum = 0;
for (Integer i: intList )
if ( i % 2 == 0 )
sum += i;
return sum;
}
在 jdk 1.5 之前,上述代码会导致编译错误,因为余数运算符 % 和一元加 += 无法应用于包装类。但在 jdk 1.5 及以上版本中,这段代码编译没有错误,将 Integer 转换为int. Java 编译器在以下条件下使用拆箱:
  • 当对象作为参数传递给需要相应基本类型的方法时。
  • 当一个对象被分配给相应原始类型的变量时。
考虑以下示例: 清单 2:显示拆箱的简单代码
import java.util.ArrayList;
import java.util.List;

public class UnboxingCheck {

public static void main(String[] args) {
Integer in = new Integer(-8);

// 1. Распаковка через вызов метода
int absVal = absoluteValue(in);
System.out.println("absolute value of " + in + " = " + absVal);

List<Double> doubleList = new ArrayList<Double>();

// Автоупаковка через вызов метода
doubleList.add(3.1416);

// 2. Распаковка через присвоение
double phi = doubleList.get(0);
System.out.println("phi = " + phi);
}

public static int absoluteValue(int i) {
return (i < 0) ? -i : i;
}
}
自动装箱和拆箱允许开发人员编写易于阅读和理解的代码。下表显示了原始数据类型及其相应的包装对象。
原始类型 外壳类
布尔值 布尔值
字节 字节
字符 特点
漂浮 漂浮
整数 整数
长的 长的
短的 短的
表 1:带有比较运算符的基本类型和等效包装类 自动装箱和拆箱可以与比较运算符一起使用。以下代码片段说明了这是如何发生的: 清单 3:显示使用比较运算符进行自动装箱和拆箱的示例代码
public class BoxedComparator {
  public static void main(String[] args) {
      Integer in = new Integer(25);
      if (in < 35)
          System.out.println("Value of int = " + in);
  }
}
方法重载时的自动打包和解包 方法重载时的自动打包和解包按照以下规则进行:
  • 当需要在扩展和封装之间进行选择时,扩展会“击败”封装;扩展是更好的选择。
清单 4:显示重载好处的示例代码
public class WideBoxed {
  public class WideBoxed {
  static void methodWide(int i) {
       System.out.println("int");
   }

  static void methodWide( Integer i ) {
      System.out.println("Integer");
  }

  public static void main(String[] args) {
      short shVal = 25;
      methodWide(shVal);
  }
 }
}
程序输出类型int
  • 扩展胜过可变数量的参数 在需要在扩展和可变数量的参数之间进行选择的情况下,扩展是更可取的。
清单 5:显示重载好处的示例代码
public class WideVarArgs {

    static void methodWideVar(int i1, int i2) {
      System.out.println("int int");
    }

    static void methodWideVar(Integer... i) {
       System.out.println("Integers");
    }

   public static void main( String[] args) {
       short shVal1 = 25;
      short shVal2 = 35;
     methodWideVar( shVal1, shVal2);
   }
  }
  • 打包优于可变数量的参数 在需要在打包和可变数量的参数之间进行选择的情况下,打包是更可取的。
清单 6:展示重载好处的示例代码
public class BoxVarargs {
     static void methodBoxVar(Integer in) {
         System.out.println("Integer");
     }

     static void methodBoxVar(Integer... i) {
         System.out.println("Integers");
     }
     public static void main(String[] args) {
         int intVal1 = 25;
         methodBoxVar(intVal1);
    }
}
使用自动打包时应记住以下事项: 众所周知,每个好的功能都有一个缺点。汽车包装在这方面也不例外。开发人员在使用此功能时应牢记的一些重要注意事项:
  • 将对象与“ ==”运算符进行比较可能会令人困惑,因为它可以应用于基本类型和对象。当此运算符应用于对象时,它实际上比较对象的引用,而不是对象本身。
清单 7:显示比较的示例代码。
public class Comparator {
   public static void main(String[] args) {
     Integer istInt = new Integer(1);
       Integer secondInt = new Integer(1);

       if (istInt == secondInt) {
         System.out.println("both one are equal");

       } else {
          System.out.println("Both one are not equal");
      }
   }
}
  • 将对象和原始类型与相等和关系运算符混合。如果我们将原始类型与对象进行比较,则该对象将被拆箱,NullPointerException如果该对象null.
  • 对象缓存。该方法valueOf()创建一个它缓存的原始对象的容器。由于值的缓存范围为 -128 到 127(含),因此这些缓存对象的行为可能有所不同。
  • 性能下降。自动装箱或拆箱会降低应用程序性能,因为它会创建不需要的对象,迫使垃圾收集器更频繁地运行。
AutoBoxing 的缺点 尽管 AutoBoxing 有许多优点,但它也有以下缺点: 清单 8:显示性能问题的示例代码。
public int sumEvenNumbers(List intList) {
          int sum = 0;
          for (Integer i : intList) {
              if (i % 2 == 0) {
                  sum += i;
              }
          }
         return sum;
   }
在这一段代码中,sum +=i 它将被扩展为sum = sum + i. 从“ +”运算符开始,JVM 开始拆箱,因为“ +”运算符不能应用于 Integer 对象。然后结果被自动打包回来。在JDK 1.5之前,数据类型int和Integer是不同的。在方法重载的情况下,使用这两种类型没有问题。随着自动打包/拆包的出现,这变得更加困难。一个例子是remove()中的重载方法ArrayList。该类ArrayList有两个删除方法 -remove(index)remove(object)。在这种情况下,不会发生方法重载,并且会使用适当的参数调用相应的方法。

结论

自动装箱是一种将原始数据类型隐式转换为相应包装类(对象)的机制。编译器通过方法valueOf()将原始类型转换为对象,通过方法IntValue()doubleValue()获取对象的原始类型。自动装箱将布尔类型转换boolean为布尔型、byte字节型char、字符型 float、浮点型、int整数型、long长整型、short短整型。拆包以相反的方向进行。 来源文章
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION