53

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

myInt.toString();

这失败并出现错误:

int cannot be dereferenced

现在,我知道原语不是引用类型(即不是对象),因此不能有方法。然而,Java 5 引入了自动装箱和拆箱(就像 C# 一样……我在 C# 中从来不喜欢它,但这无关紧要)。因此,通过自动装箱,我希望上面将 myInt 转换为 Integer ,然后对其调用 toString() 。

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

4

8 回答 8

47

Java 自动装箱/拆箱并没有达到允许您取消引用原语的程度,因此您的编译器会阻止它。您的编译器仍然知道myInt原语。jcp.org上有一篇关于这个问题的论文。

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

所以不幸的是,你必须这样做:(感谢帕特里克,我改用你的方式)

Integer.toString(myInt);
于 2008-08-07T01:09:17.547 回答
27

贾斯汀所说的同上,但你应该这样做:

Integer.toString(myInt);

它节省了一个或两个分配,并且更具可读性。

于 2008-08-07T01:16:21.263 回答
15

另一种方法是使用:

String.valueOf(myInt);

此方法对每个基本类型和Object. 这样,您甚至不必考虑您正在使用的类型。该方法的实现将为您调用给定类型的适当方法,例如Integer.toString(myInt).

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

于 2008-08-10T07:32:41.587 回答
9

对我来说似乎是规范的一个缺点

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

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”(我自己没有检查过),因为编译器选择扩大而不是自动装箱。使用自动装箱时要小心,或者根本不要使用它!

于 2008-08-07T04:16:20.480 回答
6

最接近您的示例的有效语法是

((Integer) myInt).toString();

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

Integer.valueOf(myInt).toString();

但是,它的性能不如常规用法,String.valueOf(myInt)因为,除非在特殊情况下,它会创建一个新的 Integer 实例,然后立即将其丢弃,从而导致更多不必要的垃圾。(一小部分整数被缓存,并通过数组访问进行访问。)也许语言设计者出于性能原因不鼓励这种用法。

编辑:如果downvoter(s)评论为什么这没有帮助,我将不胜感激。

于 2008-09-24T16:18:30.543 回答
2

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

同样有趣的是: Java 中的“自动装箱是一种编译器级别的 hack”。自动装箱基本上是添加到 Java 中的一个奇怪的组合。查看这篇文章以了解有关它有多奇怪的更多详细信息。

于 2010-01-23T14:16:42.277 回答
2

如果 Java 定义了某些静态方法来对原始类型进行操作并在编译器中内置一些语法糖,这将是有帮助的

5.asInteger

相当于

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

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

于 2014-01-30T23:26:36.633 回答
1

在 C# 中,整数既不是引用类型,也不必为调用ToString()而装箱。但是,它们视为框架中的对象(作为 ValueType,因此它们具有值语义)。在 CLR 中,基元上的方法通过“间接”加载到堆栈(ldind)来调用。

于 2008-09-10T21:20:19.120 回答