JavaRush /Java 博客 /Random-ZH /包装、拆包和包装

包装、拆包和包装

已在 Random-ZH 群组中发布
你好!您已经非常熟悉原始类型,并且经常使用它们。 包装、拆包和包装 - 1编程中的原语,特别是 Java 中的原语,有很多优点:它们占用很少的内存,从而提高了程序的效率,并且被明确地划分为值的范围。然而,在学习Java的过程中,我们不止一次地重复着,就像一句口头禅,“在Java中一切皆对象”。但原语是对这些话的直接反驳。它们不是物体。那么“一切皆对象”的原则是错误的吗?并不真地。在 Java 中,每个基本类型都有它的孪生兄弟,即包装类( Wrapper)。什么是包装纸? 包装器是一个特殊的类,它在其内部存储原语的值。 但由于这是一个类,它可以创建自己的实例。它们将在内部存储必要的原始值,同时是真实的对象。包装类的名称与相应基元的名称非常相似,或者完全一致。因此,记住它们会很容易。
原始数据类型的包装类
原始数据类型 包装类
整数 整数
短的 短的
长的 长的
字节 字节
漂浮 漂浮
双倍的 双倍的
字符 特点
布尔值 布尔值
包装类对象的创建就像任何其他对象一样:
public static void main(String[] args) {

   Integer i = new Integer(682);

   Double d = new Double(2.33);

   Boolean b = new Boolean(false);
}
包装类允许您减轻原始类型的缺点。最明显的一点是原语没有方法。例如,它们没有 method toString(),因此您无法将数字转换int为字符串。但有了包装类Integer就很容易了。
public static void main(String[] args) {

   Integer i = new Integer(432);

   String s = i.toString();
}
反向转换也会遇到困难。假设我们有一个我们确定包含数字的字符串。然而,在基本类型的情况下,int我们将无法从字符串中获取该数字并将其实际上转换为数字。但多亏了包装类,我们现在有了这个机会。
public static void main(String[] args) {

   String s = "1166628";

   Integer i = Integer.parseInt(s);

   System.out.println(i);
}
输出: 1166628 我们已成功从字符串中检索到数字并将其分配给引用变量Integer i。顺便说一下,关于链接。您已经知道参数以不同的方式传递给方法:基元按值传递,对象按引用传递。您可以在创建方法时使用这些知识:例如,如果您的方法适用于小数,但您需要通过引用传递的逻辑,则可以将参数传递给方法Double/Float而不是double/float. 另外,除了方法之外,包装类还有静态字段,使用起来非常方便。例如,假设您现在面临一项任务:将最大可能的数字打印到控制台 int,然后打印最小可能的数字。 这项任务似乎很简单,但如果没有谷歌,你仍然很难完成它。包装类可以轻松地让您解决以下“日常问题”:
public class Main {
   public static void main(String[] args) {

       System.out.println(Integer.MAX_VALUE);
       System.out.println(Integer.MIN_VALUE);
   }
}
这些领域可以让你不会从更严肃的任务中分心。更不用说在打印数字2147483647(这正是 MAX_VALUE)的过程中,输入错误也就不足为奇了:) 另外,在之前的一讲中,我们已经提请注意这样一个事实:包装类的对象是不可变的(Immutable)
public static void main(String[] args) {

   Integer a = new Integer(0);
   Integer b = new Integer(0);

   b = a;
   a = 1;
   System.out.println(b);
}
输出: 0引用 最初指向的对象а没有改变其状态,否则值b也会改变。与 一样String,不是更改包装器对象的状态,而是在内存中创建一个全新的对象。为什么 Java 的创建者最终决定在该语言中保留原始类型?既然一切都应该是对象,而且我们已经有了可以用来表达原语表达的一切的包装类,为什么不把它们留在语言中并删除原语呢?答案很简单——性能。原始类型之所以被称为原始类型,是因为它们缺乏对象的许多“重”特征。是的,一个对象有很多方便的方法,但你并不总是需要它们。有时您只需要数字 33 或 2.62 或true/的值false。在对象的所有好处都不重要并且程序不需要运行的情况下,基元会做得更好。

自动装箱/自动拆箱

Java中原语及其包装类的特性之一是自动装箱/自动拆箱, 包装、拆包和包装 - 2 让我们来理解这个概念。正如您和我之前已经了解到的,Java 是一种面向对象的语言。这意味着所有用Java编写的程序都是由对象组成的。基元不是对象。但是,可以为包装类变量分配基本类型的值。这个过程称为自动装箱以同样的方式,可以将原始类型的变量分配给包装类的对象。这个过程称为自动拆箱。例如:
public class Main {
   public static void main(String[] args) {
       int x = 7;
       Integer y = 111;
       x = y; // auto unpacking
       y = x * 123; // autopacking
   }
}
在第 5 行,我们将 y 的值赋给基元 x,y 是包装类的对象Integer。正如您所看到的,不需要执行任何其他操作:编译器知道这一点,int并且Integer事实上,是同一件事。这是自动拆包。第 6 行中的自动装箱也发生了同样的事情:对象 y 很容易被分配基元的值 (x*123)。这是自动打包的示例。这就是添加“自动”一词的原因:将原始引用分配给其包装类的对象(反之亦然),您不需要执行任何操作,一切都会自动发生。方便吧?:) 自动打包/自动解包的另一个很大的便利体现在方法的操作上。事实上,方法参数也受到自动打包和自动解包的影响。并且,例如,如果其中一个将两个对象作为输入Integer,我们可以轻松地向那里传递普通基元int
public class Main {
   public static void main(String[] args) {

       printNumber(7);//regular int, even without a variable
   }

   public static void printNumber(Integer i) {
       System.out.println("You entered a number" + i);
   }
}
输出: 您输入了数字 7。 反之亦然:
public class Main {
   public static void main(String[] args) {

       printNumber(new Integer(632));
   }

   public static void printNumber(int i) {
       System.out.println("You entered a number" + i);
   }
}
要记住的重要一点:自动装箱和拆箱不适用于数组
public class Main {
   public static void main(String[] args) {

       int[] i = {1,2,3,4,5};

       printArray(i);//error, won't compile!
   }

   public static void printArray(Integer[] arr) {
       System.out.println(Arrays.toString(arr));
   }
}
尝试将基元数组传递给以对象数组作为输入的方法将导致编译错误。最后,我们再次简单比较一下原语和包装 原语:
  • 有性能优势
包装纸:
  • 它们让你不违反“一切皆对象”的原则,这样数字、符号和布尔值true/false就不会脱离这​​个概念
  • 通过提供方便的方法和字段来扩展使用这些值的能力
  • 当某些方法只能与对象一起使用时是必要的
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION