在Java中,(Integer)y和new Integer(y)有什么区别?

14

以下两行代码有何区别:

Integer in = (Integer)y;

Integer in = new Integer(y);

我想要将int类型转换为Integer类型,反之亦然。这是我的代码实现:

public class CompareToDemo {

  public static void main(String[] args) {
    // Integer x=5;
    int y=25;

    System.out.println(y+" this is  int variable");

    Integer in = (Integer)y;

    //Integer in = new Integer(y);

    if(in instanceof Integer){
      System.out.println(in +" this is Integer variable");
    }
  }
}

6
为了进行此转换,您应该使用Integer.valueOf()。根据Java文档的说明,“如果不需要新的Integer实例,则通常应优先使用此方法而不是构造函数Integer(int),因为通过缓存经常请求的值,此方法可能会产生明显更好的空间和时间性能。” - Jens
3个回答

9

简单来说,

  • Integer in = (Integer)y; 使用了不必要的强制类型转换。
  • Integer in = new Integer(y); 创建了一个 Integer 实例。

详细说明每个案例

首先,让我们考虑显式转换的情况。

Integer i = (Integer)10;

编译器理解 10 是一个 int 原始类型,并且必须由其 Integer 包装才能进行编译。看起来 javac 将会执行以下操作:
Integer i = (Integer)Integer.valueOf(10);

但编译器足够智能,可以避免不必要的强制转换,(Integer) 将会被省略:

Integer i = Integer.valueOf(10);

接下来,有实例创建的情况。

Integer i = new Integer(10);

这很简单。无论如何都会创建一个Integer类的新实例。但是,正如文档所说,通常这不是适当的方式:
引用: 很少使用这些构造函数。静态工厂valueOf()通常是更好的选择,因为它可能会产生显着更好的空间和时间性能。
结论: 在日常代码编写中,我们通常使用自动装箱和拆箱。它们是基本类型和其相应的对象包装器类之间的自动转换(在Java 5中引入)。因此,您不需要过多考虑Xxx.valueOf(xxx).xxxValue()方法。这太方便了,不是吗?
Integer i = 10; // autoboxing
int j = i; // unboxing

2
“你不需要考虑。”- 这只是一个反对的观点。我并不否认虚拟机会为你处理“脏活”,但是你仍然需要了解正在发生的事情。就在前几天,有个人因为整数池机制而搞砸了线程同步的问题。 - Fildor
2
@Fildor:无论是否发生池化,使用Integer实例作为同步键都是一种破碎的设计。 - Holger
2
@Holger 我同意。但那不是我的重点。我只是想说“你不需要考虑”这句话是绝对不正确的。当然,你必须知道幕后有一些装箱/拆箱操作。否则,你迟早会遇到麻烦。那个同步问题的例子只是众多可能性之一。 - Fildor

9

如果你只想将一个int原始类型转换为一个Integer对象,你有四个选项:

   Integer in = (Integer)y;         // 1 explicit cast
   Integer in = y;                  // 2 implicit cast (autoboxing)
   Integer in = new Integer(y);     // 3 explicit constructor
   Integer in = Integer.valueOf(y); // 4 static factory method

这里最好的方法是第二种方法(自动装箱)。显式构造函数(第三种)不太好,因为它可能会有一些性能损失。
另外,它们并不严格等效。考虑以下情况:
public static void main(String[] args) {
    int x = 25;
    Integer a = new Integer(x);
    Integer b = new Integer(x);
    System.out.println(a == b);     // false
    Integer c = Integer.valueOf(x);
    Integer d = Integer.valueOf(x);
    System.out.println(c == d);     // true
    Integer e = (Integer)x;
    Integer f = (Integer)x;
    System.out.println(e == f);     // true
}

这是因为小整数被缓存了(详情请见)。

4

Java中的每个基本类型都有对应的包装类。您可以在这些基本类型和相应的包装类之间进行转换。这被称为装箱和拆箱。当您编写

Integer in = (Integer)y; //this is unnecessary casting

或者

Integer in = new Integer(y); //create a new instance of Integer class

你主要在基本类型和包装类之间进行转换。但是Java有一个特性叫做自动装箱和拆箱,Java会为你完成这些转换。只需编写即可。
int iPrimi = 20;
Integer iWrapper = iPrimi; //Autoboxing 
int iPrimi2 = iWrapper; //Auto unboxing

自动装箱和拆箱会降低性能。基本数据类型似乎比相应的Integer类型快2-3倍。因此,如果不需要使用它们,请不要使用。

你的第二个示例代码中有一个拼写错误。Interger -> Integer - Vincent
3
额玛哈格!整数! - CodeNewbie
1
最后一个例子,你的意思是 iPrimi2 = iWrapper 吗? - Jean-François Savard
是的,我指的是iPrimi2 = iWrapper。@Jean-FrançoisSavard - Emdadul Sawon

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