这是否真的在扩大与自动装箱?

时间:2008-08-07 16:30:32

标签: java primitive autoboxing

我在an answer to another question中看到了这一点,并参考了Java规范的缺点:

  

还有更多缺点,这是一个微妙的话题。检查this

public class methodOverloading{
     public static void hello(Integer x){
          System.out.println("Integer");
     }

     public static void hello(long x){
          System.out.println("long");
     }

     public static void main(String[] args){
         int i = 5;
         hello(i);
     }
}
     

这里将打印“long”(我自己没有检查过),因为编译器会选择加宽自动装箱。使用自动装箱时要小心,或者根本不使用它!

我们确定这实际上是扩大而不是自动装箱的一个例子,还是完全不同的其他内容?

在我的初始扫描中,我同意声明在i被声明为基元而不是对象的基础上输出将是“长”的。但是,如果你改变了

hello(long x)

hello(Long x)

输出将打印“整数”

这里到底发生了什么?我对Java的编译器/字节码解释器一无所知......

3 个答案:

答案 0 :(得分:13)

在第一种情况下,您正在进行扩大转化。在编译的类上运行“javap”实用程序(包含w / JDK)时可以看到这一点:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_ 5
   1:   istore_ 1
   2:   iload_ 1
   3:   i2l
   4:   invokestatic    #6; //Method hello:(J)V
   7:   return

}

显然,你会看到I2L,它是扩展Integer-To-Long字节码指令的助记符。请参阅参考here

在另一种情况下,将“long x”替换为对象“Long x”签名,您将在主方法中使用此代码:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_ 5
   1:   istore_ 1
   2:   iload_ 1
   3:   invokestatic    #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   6:   invokestatic    #7; //Method hello:(Ljava/lang/Integer;)V
   9:   return

}

所以你看到编译器创建了指令Integer.valueOf(int),用于在包装器中包装原语。

答案 1 :(得分:4)

是的,试试看吧。你会看到“长”印。它正在扩大,因为Java会选择将int加宽到很长时间才会选择将其自动放大到整数,因此选择调用hello(long)方法。

修改:the original post being referenced

进一步编辑:第二个选项打印Integer的原因是因为没有“扩展”成更大的原语作为选项,所以它必须将其打包,因此Integer是唯一的选择。此外,java只会自动装箱到原始类型,因此如果你离开hello(Long)并删除hello(Integer)会产生编译器错误。

答案 2 :(得分:2)

这个例子的另一个有趣的事情是方法重载。类型扩展和方法重载的组合仅起作用,因为编译器必须决定选择哪种方法。请考虑以下示例:

public static void hello(Collection x){
   System.out.println("Collection");
}

public static void hello(List x){
   System.out.println("List");
}

public static void main(String[] args){
   Collection col = new ArrayList();
   hello(col);
}

它不使用List的运行时类型,它使用Collection的编译时类型,因此打印“Collection”。

我鼓励您阅读Effective Java,这让我看到了JLS的一些角落案例。