是否有理由始终使用Objects而不是原语?

时间:2013-01-11 18:16:49

标签: java memory-management wrapper primitive

所以我刚开始用Java编写第二个编程类,这是教授给我们演示循环和数组的例子。

public class ArraysLoopsModulus {                       
public static void main(String [ ] commandlineArguments){                   
  //Declare  & Instatiate an Array of 10 integers
  Integer[ ] arrayOf10Integers = new Integer[10];

  //initialize the array to the powers of 2
  Integer powersOf2 = new Integer(1);   
  for(int i=0;i<arrayOf10Integers.length;i++){
    arrayOf10Integers[i] = powersOf2;
    //multiply again by 2
    powersOf2 = powersOf2 * 2;
  }

  //display the powers of 2     
  System.out.println("The first 10 powers of 2 are: ");
  for(int i=0;i<arrayOf10Integers.length;i++){
    System.out.print(arrayOf10Integers[i] + ", ");
  }  
}
}

查看了所有即将到来的示例后,我的教授似乎从不使用原始数据类型,他总是使用等效的对象类(在本例中为Integer而不是int和{{1而不是Integer[])。另外我理解某些情况需要使用对象。我的问题是:

总是使用该对象有什么可能的原因?特别是在这种简单的情况下,使用原语似乎更适合

总是这样做是不是很糟糕?我是否应该总是使用这些对象来让他开心,但在现实生活中要知道在可能的情况下使用原始数据类型

我将这个例子视为糟糕的编程吗?

由于

修改 感谢所有出色的答案,我(初学者)只需要确认我在这里看到的不是最好的编码方式。

9 个答案:

答案 0 :(得分:11)

  

总是使用该对象有什么可能的原因?

没有理由,这段代码很难看。作为对象的基元在使用集合时具有优势,但在您的示例中不使用它们。

  

特别是在这种简单的情况下,使用原语似乎   适合更好

绝对正确,在这种情况下,对象更糟糕,它们需要更多内存,并且在您的示例中没有任何优势。

  

总是这样做是不是很糟糕?

是的,如果需要,您应该只使用对象(盒装基元)。除了在集合中使用之外,这样的对象也可以是null,这是一个优点,可以用作“值不存在(尚未存在)”等。

  

我是否应该总是使用这些物品来让他开心,但要知道   现实生活中尽可能使用原始数据类型

不,告诉他这没用。但请记住,你的教授从来不想给上学前课程。他可能“被迫”这样做了。

  

我将这个例子视为糟糕的编程吗?

是。最大的坏!

答案 1 :(得分:8)

来自约书亚布洛赫的Effective Java

  

第49项:将基本类型选择为盒装基元。   原始类型和盒装基元之间有三个主要区别:

     
      
  • 原语只有它们的值,而盒装原语的身份与其值不同。

  •   
  • 原始类型不能为空,但是盒装基元可以。

  •   
  • 原始类型比盒装基元更具空间和时间效率。

  •   
     

必须小心使用带有盒装基元的==运算符,与任何其他引用类型一样,它会比较标识,您几乎肯定希望比较值。如果将带框的基元与带有==运算符的基元进行比较,则将基元类型装箱并比较标识,因此也必须小心。

     

装箱和拆箱的过程,特别是在循环中会严重影响性能。

     

基本上,应该避免使用box原语,除非不能使用原始类型,例如在集合中或作为参数化类型。

我希望这有助于您了解其中的差异。

答案 2 :(得分:4)

大多数人都同意你应该尽可能使用原语。为了扮演魔鬼的拥护者,我想到了一个优势:他们更快失败

此代码将抛出空指针异常,因为您忘记初始化myInteger

private Integer myInteger;

public void run () {
    int myNewInt = myInteger + 5;
}

如果您使用int,它会继续进行,并且更难注意到您犯的错误。


这是我刚遇到的另一个类似优势:它让你代表缺少数据。我有一个返回配置选项的方法。它有一个返回boolean的签名。结果是系统中不存在配置选项。但不是告诉我,它只是默认为false(它必须选择某些东西)。结果,我认为这个值设置为false但结果却丢失了。如果方法返回Boolean

,则错误会更明显

答案 3 :(得分:1)

E.g。原语不能存储在Collectins

好的自动装箱有帮助,但帽子只是由编译器包装而不是你自己的。

答案 4 :(得分:1)

不,你不应该在任何地方使用原始类型的Object包装器:

1)对象等价物使用更多的内存然后使用原始类型。

2)它可能导致两个Integer对象的比较无效 - 您应该使用equals方法对它们进行比较 - 这不方便。

使用Object包装器的唯一合理原因是generics,您必须使用一些Class。例如,List<Integer>Map<Integer, Double>等集合。

另一个原因是你必须存储null变量值而不是任何数字。

提供的代码块有很多冗余部分。

答案 5 :(得分:1)

基元更节省空间,因为对象包装器创建一个新的对象只是为了保存您通常使用的相同基元。 Java现在有很多优化,使得教授的代码不会完全缓慢/破坏,但这肯定是一种不好的做法。

一般情况下,你应该在任何需要的地方使用原语,除非你发现你需要对象支持,特别是像@ MrSmith42建议的那样,如果你想在Java Collection中存储基元,比如ArrayList。

很少有任何理由创建包装器对象数组。原始数组非常节省空间,对象数组会失去所有效率。

答案 6 :(得分:0)

powersOf2 = powersOf2 * 2;

如何移动字节?!

//转换为原始而不是:

powersOf2  = powersOf2 << 2; 

答案 7 :(得分:0)

根据The Number Classes教程中的Java文档,它只指出了三个可能想要使用Number对象而不是基元的原因。我认为,下面未列出的任何其他原因将被视为糟糕的编程。

  
      
  1. 作为期望对象的方法的参数(通常在操作数字集合时使用)。
  2.   
  3. 使用类定义的常量,例如MIN_VALUE和MAX_VALUE,它们提供数据类型的上限和下限。
  4.   
  5. 使用类方法将值转换为其他基本类型,从而转换为字符串和从字符串转换,以及在数字系统之间进行转换(十进制,八进制,十六进制,二进制)。
  6.   

答案 8 :(得分:0)

与这里的流行观点相反,我和你的教授在一起。我更喜欢在很多时候使用原始包装对象。我认为可以归结为编程风格。

示例:我有一个方法可以调用数据库以获取一个int。该方法返回一个Integer对象。如果int不存在,则可以返回空对象。如果它返回一个非null对象,那么我知道该项目存在于数据库中并且是有效数字。

使用原语时,您必须返回数字或引发异常,但有时这两者都不适合。

因此,我确实认为有很多使用包装类型对象的正当理由。大多数人不使用它们的原因是他们的表现不佳。这通常是过早的优化,在实际的代码库中,编写简单,健壮的代码通常更为重要(取决于应用程序)。