Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:为什么需要包装类?_Java_Collections - Fatal编程技术网

Java:为什么需要包装类?

Java:为什么需要包装类?,java,collections,Java,Collections,在非常高的层次上,我知道我们需要“包装”原始数据类型,例如int和char,方法是使用它们各自的包装类在Java集合中使用它们。我想通过以下问题了解Java集合在低层次上是如何工作的:“为什么我们需要将基本数据类型包装为对象,以便能够在集合中使用它们?”我提前感谢您的帮助。因为Java集合只能存储对象引用(所以您需要将基本数据类型包装起来,以便将其存储在集合中) 有关更多信息,请阅读上的这篇短文 如果你想了解细节,可以归结为以下几点: 本地原语存储在堆栈上。集合通过对堆中对象的内存位置的引用来存

在非常高的层次上,我知道我们需要“包装”原始数据类型,例如int和char,方法是使用它们各自的包装类在Java集合中使用它们。我想通过以下问题了解Java集合在低层次上是如何工作的:“为什么我们需要将基本数据类型包装为对象,以便能够在集合中使用它们?”我提前感谢您的帮助。

因为Java集合只能存储对象引用(所以您需要将基本数据类型包装起来,以便将其存储在集合中)

有关更多信息,请阅读上的这篇短文

如果你想了解细节,可以归结为以下几点:


本地原语存储在堆栈上。集合通过对堆中对象的内存位置的引用来存储其值。要获取本地原语的引用,您必须选择框(获取堆栈上的值并将其包装以存储在堆上)值。

基元数据类型不能作为内存地址引用。这就是为什么我们需要包装器作为基元值的占位符。然后可以对这些值进行变异和访问、重新组织、排序或随机化。

请参阅


这是针对C#,但同样的概念也适用于Java。John Skeet给出了答案。

原因是Java集合不区分原语和对象。它将它们都作为对象处理,因此需要一个包装器。您可以轻松构建自己的集合类,而不需要包装器,但最终,您必须为每个类型构建一个,char、int、float、double等乘以集合的类型(Set、Map、List及其实现)

你能想象那有多无聊吗


事实上,对于大多数应用程序来说,不使用包装器所带来的性能几乎可以忽略不计。但是,如果您需要非常高的性能,也可以使用一些用于基本集合的库(例如

在集合中存储基元类型值。我们需要包装类。

在虚拟机级别,这是因为基元类型在内存中的表示方式与引用类型(如java.lang.Object及其派生类型)非常不同。例如,java中的基元int在内存中只有4个字节,而对象在它本身至少有8个字节,再加上4个字节用于引用它。这种设计简单地反映了CPU可以更有效地处理基本类型这一事实

所以,对于您的问题“为什么需要包装器类型”的一个答案是因为它能够提高性能

但对于程序员来说,这种区别增加了一些不必要的认知开销(例如,不能在集合中使用int和float)事实上,通过隐藏这种区别来进行语言设计是很有可能的——许多脚本语言都这样做,CLR也这样做。从1.5开始,Java也这样做。这是通过让编译器在原语表示和对象表示之间无声地插入必要的转换来实现的(通常称为装箱/拆箱。)


所以你问题的另一个答案是,“不,我们不需要它",因为编译器会自动为您执行此操作,并且在某种程度上您可以忘记幕后发生的事情。

集合使用泛型作为基础。集合框架设计用于收集、存储和操作任何类的数据。因此它使用泛型类型。通过使用泛型,它能够存储任何类的数据在其声明中指定其名称的类

现在,我们有各种场景,希望以与集合工作相同的方式存储基元数据。我们无法使用ArrayList、HashSet等集合类存储基元数据,因为集合类只能存储对象。因此,为了在集合中存储基元类型,我们提供了包装类。

编辑: 拥有包装器类的另一个好处是,缺少对象可以被视为“无数据”。对于primitive,您将始终拥有一个值

假设我们有方法签名

public void foo(字符串aString,int-aNumber)

在上述方法签名中,不能将
aNumber
设置为可选

但如果你做了如下签名:

public void foo(字符串aString,整数aNumber)

您现在已经将
aNumber
设置为可选,因为用户可以将
null
作为值传递。

包装类提供了与相应数据类型相关的有用方法,您可以在某些情况下使用这些方法

一个简单的例子.考虑这个,

Integer x=new Integer(10); 
//to get the byte value of 10
x.byteValue(); 

//but you can't do this,
int x=10;
x.byteValue(); //Wrong!

您能理解这一点吗?

如果已知变量包含表示
null
的特定位模式或可用于定位Java虚拟机对象头的其他信息,并且如果给定与
null关联的位模式,读取给定引用的对象头的方法将固有陷阱,则JVM可以在假设存在一个变量的情况下访问该变量标识的对象。如果某个变量可能包含无效引用但不是特定的
null
位模式的内容,则尝试使用该变量的任何代码都必须先检查它是否标识了对象。这将大大降低降低JVM的速度

如果
对象
派生自
任何东西
,类对象派生自
对象
,但原语继承自另一个派生自
任何东西
的类,那么在64位实现中,可以说大约3/4的可能位模式将代表
双值2^512,其中1/8表示+/-11529215040606846975范围内的
值,几十亿表示任何其他元素的任何可能值,1/256表示标识对象。对事物的多种操作
Integer wrapperInt = new Integer("10");
Integer i = new Integer("1"); //new object is created
 Integer i  = Integer.valueOf("100"); //100 is stored in variable