代码之家  ›  专栏  ›  技术社区  ›  Mike Stone

为什么Java自动装箱不能扩展到自动装箱类型的方法调用?

  •  49
  • Mike Stone  · 技术社区  · 16 年前

    我想将原语转换为字符串,并尝试:

    myInt.toString();
    

    失败原因如下:

    int cannot be dereferenced
    

    现在,我知道基元不是引用类型(即,不是对象),因此不能有方法。然而,Java 5引入了自动装箱和解包(LaC)…我从来都不喜欢C,但这不是重点)。因此,对于autoboxing,我希望上面的内容将myint转换为整数,然后对此调用toString()。

    此外,我相信C允许这样的电话,除非我记错了。这只是Java自动装箱/拆箱规范的一个不幸的缺点,还是有一个很好的理由?

    8 回复  |  直到 11 年前
        1
  •  45
  •   yoozer8    13 年前

    Java自动装箱/解包不能达到允许去引用一个原语的程度,因此编译器会阻止它。你的编译器仍然知道 myInt 作为原始人。有篇关于这个问题的论文在 jcp.org .

    自动修改主要在赋值或参数传递期间有用——允许您将原语作为对象传递(反之亦然),或者将原语分配给对象(反之亦然)。

    所以不幸的是,你必须这样做:(尊敬的帕特里克,我转向你的方式)

    Integer.toString(myInt);
    
        2
  •  27
  •   Patrick    16 年前

    贾斯汀说的话也是一样,但你应该这样做:

    Integer.toString(myInt);
    

    它节省了一两个分配,而且可读性更强。

        3
  •  15
  •   SaM    16 年前

    另一种方法是使用:

    String.valueOf(myInt);
    

    对于每个基元类型和 Object . 这样你就不用考虑你使用的类型了。方法的实现将为您调用给定类型的适当方法,例如 Integer.toString(myInt) .

    http://java.sun.com/javase/6/docs/api/java/lang/String.html .

        4
  •  9
  •   Mike Stone    16 年前

    似乎是一个缺点 向我说明

    还有更多的缺点,这是一个微妙的话题。检查 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”(长),因为编译器选择扩展而不是自动氧化。使用自动氧化时要小心,否则不要使用它!

        5
  •  5
  •   erickson    16 年前

    最接近示例的有效语法是

    ((Integer) myInt).toString();
    

    当编译器完成时,这相当于

    Integer.valueOf(myInt).toString();
    

    但是,它的性能不如传统用法好, String.valueOf(myInt) 因为,除了特殊情况外,它会创建一个新的整数实例,然后立即将其丢弃,从而产生更多不必要的垃圾。(缓存一小范围的整数,并通过数组访问进行访问。)出于性能原因,语言设计者可能希望不鼓励这种使用。

    编辑:如果投反对票的人评论为什么这没有帮助,我会很感激的。

        6
  •  1
  •   Mark Cidade    16 年前

    在C中,整数既不是引用类型,也不必装箱以便 托斯特林() 被召唤。他们 但是,在框架中考虑对象(作为一个值类型,因此它们具有值语义)。在clr中,基元上的方法是通过“间接”将它们加载到堆栈(ldind)来调用的。

        7
  •  1
  •   Dan Rosenstark    15 年前

    正如每个人都指出的,自动氧化可以简化一些代码,但不能假装原语是复杂的类型。

    同样有趣的是: "autoboxing is a compiler-level hack" 在Java中。自动装箱基本上是添加到Java上的一种奇怪的蹩脚货。退房 this post 了解更多关于它有多奇怪的细节。

        8
  •  1
  •   supercat    11 年前

    如果Java定义了某些静态方法对基元类型进行操作,并在编译器中编译一些语法糖,那么这将是有帮助的。

    5.asInteger
    

    相当于

    some.magic.stuff.Integer.asInteger(5);
    

    我不认为这样的特性会导致与任何根据当前规则编译的代码不兼容,而且在许多情况下它会帮助减少语法混乱。如果Java是对AutoBox原语进行引用的,人们可能会认为它是将撤销引用语法映射到静态方法调用(这实际上是.NET中发生的),因此以这种形式编写的操作不会比等效静态方法调用更昂贵。添加一个新的语言特性来鼓励人们编写糟糕的代码(例如自动装箱取消引用的原语)似乎不是一个好主意,尽管允许取消引用的样式方法可能是。