为什么在java中有每个基本类型的包装器
Number
子类包装原始数字类型( Byte
, Integer
, Double
, Float
, Long
和Short
)。
他们的目的是什么?
创建了这些包装类,以便有一些方法可以将这些原始类型与各种容器类(如ArrayList
。 由于原始类型不能直接强制转换为Object
引用,因此它们存储在包装类中,以允许在需要Object
引用的地方使用它们。
因为包装器是Objects
。
-
Collections
需要对象 - 对象可以
instantiated
null - 如果你在一个原语中实例化为-1,我们可以得到
NullPointerException
而不是奇怪的行为 - “包装”具有方便的方法
许多早期的面向对象语言(Smalltalk等)对所有值都有一个共同的“顶级类型” ,这使得更容易定义与它们穿梭的值类型无关的generics操作。
类型理论中的顶部类型,通常缩写为顶部或由向下标记符号(⊤),是通用类型 – 该类型包含感兴趣的类型系统中的每个可能的对象。
Java没有这样的顶级类型,但是Object
最接近它。 具有从原始值到Object
实例的映射允许它有效地用作顶部类型。
核心语言工具java.lang.reflect
使用Object
作为顶级类型的替代 – 当您reflection性地调用在Object
传递并返回Object
。
根据这个链接, java教程的原因是:
有三个原因可以使用Number对象而不是基元:
- 作为期望对象的方法的参数(通常在操作数字集合时使用)。
- 使用由类定义的常量(如MIN_VALUE和MAX_VALUE),它们提供数据类型的上限和下限。
- 使用类方法将值转换为与其他基本类型之间的值,从而转换为字符串和从字符串转换,以及在数字系统之间进行转换(十进制,八进制,hex,二进制)。
Java设计者 – 有充分的理由或不好 – 选择不将所有类型都基于Object
。 像int
, long
, char
等原始类型不是基于Object
,因此它们具有相当不同的语义,就像它们通过值而不是通过引用传递。
Integer
/ Long
基本上只是包装类,使原始类型的行为与任何其他类型一样,以便能够在类或对象更适合的上下文中使用它们。
例如,由于语义不同,集合必须有两个版本,一个用于Object,另一个用于基本类型。 只需制作单个版本的集合并包装原始类型就更容易了。
Java API中的包装类基本上有两个主要用途:
- 让基元包含在为对象保留的活动中,例如添加到集合中,或从具有对象返回值的方法返回。
- 为基元提供各种实用程序function。 这些函数中的大多数与各种转换有关:将原语转换为String对象,以及将原语和String对象转换为不同的基数(或基数),例如二进制,八进制和hex。
将它们视为对象并将它们放入List,Maps等
因此,我们能够将原始数据类型添加到集合中。 要将元素添加到集合中,它们必须是类型objects
。 因此,引入了Wrapper类,它们可以创建primitive data types
对象。
例如:
Arraylist : add(Object o) TreeSet: add(Object o)
就个人而言,我使用它们作为方法的参数,所以我不必担心传入的数字的类型。然后我可以使用像doubleValue()这样的方法来获取值并且可以继续而不用担心传递的内容在。
这是拥有抽象基类的基本原因。
有一种特定类型的“指针”可以指向任何类型(如C / C ++中的void
)。
我指的是java.lang.Object
。
例如,你可以这样做:
List aList = new ArrayList (); Object o = aList;
但这不适用于基元,即基元没有void
引用类型。 即原始类型无法引用任何类型的原始类型。
因此,如果您想要一个对任意变量进行操作的算法,您可以使用java.lang.Object类型的变量。
如果任意值是基元,请使用适当的Object Wrapper来包装它们,并使用java.lang.Object引用来操作它们。
您也可以在Collections
看到这一点
包装类是原始数据类型的对象代表,因此只要有将它们用作对象的情况,我们就必须使用它们。 当需要效率时我们需要对象和原语时的包装器使用。
1st – 为了使java完全面向对象。
第二个 –我们不能通过引用方法传递一个原始类型,并且java实现的许多标准数据结构都在对象上运行:例如(ArrayList,HashSet,HashMap等),所以它们需要这些对象参考