何时在Java中使用原始类型和引用类型

33

什么情况下应该使用原始类型(int)或引用类型(Integer)?

这个问题引起了我的好奇心。

11个回答

33

什么情况下应该使用原始类型(int)或引用类型(Integer)?

通常情况下,我会使用原始类型(例如int),除非必须使用包装原始类型的类。

其中一个必须使用包装类(例如Integer)的情况是在使用generics时,因为Java不支持将原始类型用作类型参数:

List<int> intList = new ArrayList<int>();               // Not allowed.
List<Integer> integerList = new ArrayList<Integer>();   // Allowed.

在许多情况下,我会利用自动装箱和拆箱,这样我就不必显式地执行原始类型到其包装类的转换,反之亦然:

// Autoboxing will turn "1", "2", "3" into Integers from ints.
List<Integer> numbers = Arrays.asList(1, 2, 3); 

int sum = 0;

// Integers from the "numbers" List is unboxed into ints.
for (int number : numbers) {
  sum += number;
}

此外,当将基本数据类型转换为其包装类对象时,并且不需要唯一实例对象时,请使用包装器提供的valueOf方法,因为它执行缓存并为特定值返回相同的实例,从而减少创建的对象数量:
Integer i1 = Integer.valueOf(1);   // Prefer this.
Integer i2 = new Integer(1);       // Avoid if not necessary.

如果想要了解valueOf方法的更多信息,可以参考Integer.valueOf方法的API规范,以了解这些方法在原始类型的包装类中的行为。


11

这真的取决于上下文。首先,优先选择原始类型,因为它更直观且开销较小。如果由于泛型/自动装箱的原因不可能使用原始类型,或者您希望它可以为空,则请使用包装类型(您所称的复杂类型)。


另一个需要考虑的问题是您是否需要区分没有值(null)和零。 - Chandra Sekar

4
我在创建API时遵循的一般规则可以总结如下:
  1. 如果方法必须返回一个值,则使用基本类型。
  2. 如果该方法可能不适用于某些情况(例如,在没有ID的对象上调用getRadioId(...)),则返回一个Integer,并在JavaDocs中说明该方法有时会返回null。

关于第二点,当自动装箱时要注意NPE。 如果您定义了一个方法:

public Integer getValue();

然后按以下方式调用:

int myValue = getValue();

如果getValue()返回null,你将会得到一个没有明显原因的NPE错误。

3

由于Java执行所谓的auto-boxing and auto-unboxing,因此出于开销较小的考虑,在大多数情况下应使用原始类型int

唯一必须使用Integer的情况是在泛型中。

List<int> list; // won't compile
List<Integer> list; // correct

当尝试在期望对象的地方使用原始类型时。 - Joey

2

我的经验法则是:只有在必须使代码编译时才使用包装过的基本类型。在您的代码中,原始包装类的名称应该出现在泛型类型参数和静态方法调用中:

List<Integer> intList = new ArrayList<Integer>();

int n = Integer.parseInt("123");

这是我会给新的Java程序员的建议。随着他们的学习,他们将遇到需要更加有鉴别力的情况,比如处理Maps或数据库,但那时他们也应该更好地理解原始类型和装箱基本类型之间的区别。
自动装箱使我们相信int和Integer(例如)是可以互换的,但这是一个陷阱。如果您不加区别地混合两种值,可能会使用“==”比较两个Integer值或尝试取消框定null而没有意识到它。由此产生的错误可能是间歇性的并且很难跟踪。
比较装箱基本类型与“==”有时像进行值比较一样工作,这并不有助于解决问题。这是自动装箱过程中某些范围内的值被自动缓存的结果造成的幻觉。这与我们总是遇到的字符串值问题相同:将它们与“==”进行比较有时会“起作用”,因为实际上你在比较两个引用指向相同的缓存对象。
处理字符串时,我们只需告诉新手永远不要使用“==”来进行比较,就像我们一直在做的那样。但是,使用“==”比较原始类型是完全有效的;这个技巧(由于自动装箱)是确保值真正是原始类型。编译器现在允许我们将变量声明为“Integer”并将其用作“int”,这意味着我们必须更加严格地行事,并在没有充分理由的情况下进行此操作时将其视为错误。

2

在某些情况下,使用Integer可能更好,例如当您使用允许为空的数字输入的数据库时,因为您无法用int表示空值。

但是,如果您进行纯数学计算,则像其他人提到的那样,由于直观性和开销较小,最好使用int


2

我知道有点晚了,但是为了万一,我想发表一下我的意见。

在某些情况下,需要使用包装器,因为缺少值与默认值不同。

例如,在我工作的一个项目中,屏幕上有一个字段,用户可以输入双精度浮点数。业务需求清楚地说明,如果用户输入0,则意义与未输入值并留空的情况不同。这种差异将在另一个模块中产生影响。因此,在这种情况下,我们必须使用Double对象,因为无法使用原始数据类型表示缺少值;由于原始数据类型将默认为0,而这是该字段的有效输入。


1

与其称它们为“复杂类型”,不如将 Integer、Double 等视为“类”,将 int、double 等视为“基本类型”。

如果你在进行任何复杂的数学运算,基于类的数字表示法(如 Integer 和 Double)会让你感到繁琐和缓慢 - 许多数学运算只能使用基本类型。

另一方面,如果你想将数字放入像列表和映射这样的集合中,那么这些集合只能包含对象 - 因此你必须使用(或转换为)Integer 和 Double 这样的类。

个人而言,我尽可能使用基本类型,并且仅在需要进行输入或输出时才转换为类表示法,而传输需要这些表示法。

然而,如果你根本没有进行任何数学运算,而是直接通过代码传递值,那么通过处理基于类的形式(如 Integer)可能会节省你一些麻烦。


0

我认为没有什么特定的规则。当我编写方法签名、Maps、集合、传递的数据对象时,我会选择类型而不是原始类型(例如Integer而不是int)。因此,即使在方法内部等地方,我仍然喜欢使用Integer而不是int。但如果你认为这样做太麻烦(需要多打一个“eger”),那么在本地变量中使用int也是可以的。


0

如果您想要在servlets中将setAttribute设置为session,您必须使用Integer、Boolean、String等对象。如果您想要使用值,可以使用基本数据类型。对象可能为空,但原始数据类型不可能为空。如果您想要对原始数据类型进行类型比较,请使用“==”,但是对于对象,请使用“.equals”,因为在对象比较中,“==”并不会比较值,它只会检查它们是否是相同的对象。使用基本数据类型可以使代码更快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接