何时使用包装器类和原始类型


Answers:


69

其他人提到某些结构(例如Collectionsrequire对象),并且对象比原始对象(内存和装箱)的开销更大。

另一个考虑因素是:

将对象初始化为null或将null参数发送到方法/构造函数中以指示状态或功能可能很方便。使用原语不能做到这一点。

许多程序员将数字初始化为0(默认值)或-1来表示这一点,但是根据具体情况,这可能是错误的或令人误解的。

NullPointerException当某些东西被错误地使用时,这也将为场景打下基础,这比程序中的一些任意错误更加对程序员友好。


15
“将对象初始化为null可能很方便”。它不方便,因为这是不正确的,如果该字段是可选的,则应明确指出。
Eddie Jamsession 2015年

8
大声笑@EddieJamsession谢谢,我永远不会再初始化为null。(pfffft)
pstanton'2

@EddieJamsession如果在设置实际值失败时将Objects初始化为null以指示失败,那么您还打算如何解决此问题?哦,我刚输入时就意识到:例外。NullPointerException太通用;最好使用非常具体的自定义异常来指示出了什么问题。好,我从现在开始就要做...
klaar

1
@EddieJamsession阅读完此内容后,我遇到了Optional对象的概念。对。
klaar

18

通常,除非出于某种原因(例如放入集合)需要对象,否则应使用基本类型。即使这样,如果要最大化数值性能,也可以考虑使用不需要对象的其他方法。这是由文档建议,并且本文演示了自动装箱如何导致较大的性能差异。


3
对性能的影响不是很大,以至于代码的易读性/可靠性应放在第二位。
pstanton

2
首先,适当地使用原语不会使您的代码难以辨认。其次,在某些情况下,性能影响很大。说从来没有,这很荒谬。
马修·弗莱申

1
@pstanton:请说明如何Integer比更具可读性int
斯蒂芬·C

在许多情况下,Integer比int更清晰易懂,在这些情况下,我将始终使用int,或者如果我知道某个变量永远不会为null,我将使用int,因为正如您指出的那样,int效率更高。但是,在许多情况下,另一个程序员在使用对象时更容易理解变量的状态,因为可以将其初始化为null来表示它尚未准备就绪。例如,如果您有一个未保存的数据库记录,且该记录具有唯一的递增数字ID,那么在为其分配有效ID之前,应将此ID为0,-1还是null?在这种情况下,对象会更好。
pstanton

关于性能-在特殊情况下,性能下降可能会很严重,即,如果您很快创建了许多这些对象,或者在一段时间内建立了许多对象,则可能会产生很大的影响。但是,我希望一个体面的程序员能够识别这些特殊情况,从而避免或相应地进行修改。我从来没有说过它从来没有意义,但是总的来说,它没有意义。
pstanton

12

我认为,如果我的类成员是包装器变量,则它不依赖默认值,这是开发人员友好的行为。

1。

class Person {
   int SSN ; // gets initialized to zero by default 
}

2。

class PersonBetter {
  Integer SSN; //gets initialized to null by default
}

在第一种情况下,您不能保持SSN值未初始化。如果在尝试使用该值之前不检查该值是否已设置,可能会造成伤害。

在第二种情况下,可以将SSN初始化为null。这可能导致NullPointerException,但总比不知不觉地在不初始化SSN字段的情况下尝试将默认值(零)作为SSN插入数据库要好。


3
构建器模式旨在解决这个问题。在这种情况下,PersonBuilder如果在调用“ build”获取Person实例之前未设置SSN,则将引发一个异常。我认为这种事情太过分了,但这就是Java语言提倡的正确模式。
桑迪·查普曼

8

如果需要,我只会使用包装器类型。

除了使用它们之外,使用它们不会带来太多收益Objects

而且,您会浪费内存使用量以及装箱/拆箱所花费的时间。


4
您可能不会获得太多收益,但是您也不会损失太多。除非您使用的是1990年代的掌上电脑飞行员。
pstanton

它们是对象这一事实也给它们提供了更多的上下文和封装,而不是单纯的原始语言。因此,实际上取决于这些原语的含义以及在何处使用它们,您可能会实际获得很多收益。
aberrant80

4

实际上,我遇到了可以解释使用包装器类的情况。

我创建了一个具有long类型变量的服务类

  1. 如果变量的类型long-未初始化时将其设置为0-在GUI中显示时,这会使用户感到困惑
  2. 如果该变量的类型Long-未初始化时将被设置为null-此空值将不会在GUI中显示。

这也适用于Boolean当我们使用基本类型boolean(默认值是false)时,值可能更令人困惑的地方。


3

集合是简单Java包装器对象的典型情况。但是,您可以考虑在代码(值对象)中赋予包装器更具体的含义。

恕我直言,将价值对象归结为代码的可读性和可维护性几乎总是有好处。当对象承担某些职责时,将简单的数据结构包装在对象内部通常会简化代码。这在领域驱动设计中非常重要。

当然存在性能问题,但是我倾向于忽略它,直到我有可能使用适当的数据来衡量性能并针对有问题的区域采取更有针对性的行动。如果代码也易于理解,则也可能更容易理解性能问题。


3

通过使用原语,可以大大受益于以数值计算为主的应用程序的性能

基本类型,使用==运算符,但是对于包装器,首选是调用equals()方法。

“原始类型被认为是有害的”,因为它们将“过程语义”混入了其他统一的面向对象模型中。

许多程序员将数字初始化为0(默认值)或-1来表示这一点,但是根据具体情况,这可能是错误的或令人误解的。


1

如果要使用Collections,则必须使用Wrapper类。

基本类型,用于数组。同样,代表没有行为的数据,例如计数器或布尔条件。

自从自动装箱以来,“何时使用原始或包装器”边界变得非常模糊。

但是请记住,包装器是对象,因此您可以获得所有奇特的Java功能。例如,可以使用反射创建Integer对象,但不能创建int值。包装器类还具有诸如valueOf之类的方法。


除了集合,我不应该使用包装器类吗?如何将其用于像Integer这样的普通声明i = new Integer(10); 这样好吗?
Gopi

自动装箱允许您执行整数i = 10;
汤姆

1
不,斯里 如果您不要求我成为对象,请不要使其成为一个对象。
马修·弗拉申

自动装箱是否会将上述声明的i拆箱为int i = 10或Integer i = 10?
Gopi

3
int pi =新的Integer(10); 作品。整数oi = 10; 作品。int ni = null; 不起作用。LHS转换为RHS所需的任何内容。
pstanton

0

如果要创建值类型。类似于ProductSKU或AirportCode。

当基本类型(在我的示例中为字符串)定义相等时,您将需要覆盖相等。


5
字符串不是原始字符串
pstanton's October

2
仍然有充分的理由将包含字符串的值类型包装为基础对象。
克里斯·米萨尔

你的答案就是没有道理的。我不确定你在说什么。但是,我同意您的意见,如果包装类可以提高可读性,则是个好主意。
pstanton

值类型或值对象应该被创建并且是不可变的。例如,创建“ CountryCode”对象(例如:new CountryCode(“ USA”))然后以相同的方式创建另一个对象(后来又有所不同)是没有意义的。它们只是开始的字符串,但它们背后具有含义。通过使用字符串,您可以修改它们(通过添加更多数据等),但是它们将不再相等。请参阅这篇文章,以更好地说明我要解释的内容:)我希望这有意义 c2.com/cgi/wiki?ValueObject
克里斯·

0

Java中的原始值不是对象。为了将这些值作为对象进行操作,java.lang包为每种原始数据类型提供了一个包装器类。

所有包装器类都是最终的。可以启动的所有包装器类的对象都是不可变的,这意味着不能更改包装器对象中的值。

虽然void类被认为是包装器类,但是它不包装任何原始值并且是不可初始化的。它没有公共构造函数,仅表示代表关键字void的类对象。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.