【问题标题】:Java Integer vs. String Autoboxing DesignJava 整数与字符串自动装箱设计
【发布时间】:2012-04-28 09:39:20
【问题描述】:

在 Java 中,我可以执行以下操作来简洁地防范 NullPointerException

if ("myString".equals(someOtherString))

但我不能对整数做同样的事情,例如

if (5.equals(someOtherInteger))

我得到一个编译时错误。关于为什么做出这个设计决定的任何想法?或者任何可以解释它的资源?提前致谢。

编辑someOtherIntegerInteger,而不是 int

【问题讨论】:

  • Integer 是一个对象。 int 是原始类型,就像 C 中的 ints。因此,它没有继承自 Object.equals() 方法。
  • @Travis 那么,您的问题是为什么 Java 语言不提供语法糖来允许在应用点 (.) 运算符时自动自动装箱原始整数,以便您可以简单地编写这个 Yodah 类型的谓词?我做对了吗?
  • @edalorzo 你明白了。真实性的答案提供了迄今为止所有答案中最深刻的见解。
  • @Travis 我的好同事,有一百万件事我想知道为什么 Java 不做。而且我几乎认为答案很简单,因为它就是这样。互联网上充斥着关于如何改进 Java 的好主意,但它们都需要时间、金钱和人力资源,因此,它们被投资在更重要的地方。我认为没有任何官方文档说明为什么没有实现这一点,但我们当然可以将它添加到一长串好主意中,如果它还没有的话。
  • @edalorzo 这不是功能要求,只是一个问题。而且,Jeffrey 刚刚提供了一些您声称不存在的文件。

标签: java autoboxing


【解决方案1】:

String 在 Java 中一直是一个对象。字符串没有自动装箱,原则上也不可能。最近引入了从原始 intInteger 对象的自动装箱。

询问为什么尝试访问基元的成员变量不会调用自动装箱是有效的(95.toString(radix) 实际上会很方便),但我想原因是它不被认为是一个可能的用例,因为几乎每个wrappedPrimitive.method() 都有一个等效的WrapperClass.method( primitive ) 版本。

equals() 对于原始类型通常是不必要的,因为== 已经存在。但是,您确实为它提供了一个很好的案例作为 null-guard...5 == integerInstance 将尝试拆箱实例,如果实例是 null,则抛出 NullPointerException,不幸的是。 (一开始我并没有完全理解你的观点。)

也就是说,如果我们能听到目前或在引入自动装箱时从事 Java 工作的人关于他们是否考虑过这种功能,那将是非常酷的。

【讨论】:

  • 感谢您真正阅读我的问题并提供有见地的答复。
【解决方案2】:

JLS 指定装箱转换只能在赋值转换、方法调用转换或强制转换期间发生。由于您既没有将 5 分配给变量,也没有将其作为参数传递给方法,也没有显式地将其强制转换为 Integer,因此不会为您自动装箱。

赋值转换(§5.2, §15.26)转换类型 表达式到指定变量的类型。

分配转换可能会导致 OutOfMemoryError(由于 装箱转换(§5.1.7)),NullPointerException(由于 拆箱转换(第 5.1.8 节))或 ClassCastException(由于 在运行时抛出未经检查的转换(第 5.1.9 节)。

方法调用转换(§5.3、§15.9、§15.12)适用于每个 方法或构造函数调用中的参数,并且除了一个 情况下,执行与赋值转换相同的转换。

方法调用转换可能会导致 OutOfMemoryError(作为 装箱转换的结果(§5.1.7)),NullPointerException(作为 拆箱转换的结果(第 5.1.8 节))或 ClassCastException(作为 未经检查的转换(第 5.1.9 节)的结果)将在运行时抛出。


铸造上下文允许使用以下之一:

...

装箱转换(第 5.1.7 节)可选地后跟加宽 参考转换(§5.1.5)

【讨论】:

  • @TravisWebb 哎呀,我忘了铸造转换。也添加了。
【解决方案3】:

你可以使用

if (someOtherInteger!=null && someOtherInteger == 5)

【讨论】:

  • 如果someOtherIntegernull,你会得到一个NullPointerException(假设它是一个Integer)。
  • 除了有据可查的 == != .equals()
  • @TravisWebb 在原语的情况下,它没有任何方法。
  • Integer 不是原语。
  • 是的,确实需要检查 null。
【解决方案4】:

我怀疑自动装箱没有为文字 5 实现,而它是为字符串 myString 实现的,作为安全措施。自动装箱一个带有双引号 "" 的句法结构是安全的,因为引号不太可能是无意的,因此用户的意图很明确并且不会损害类型安全。

但是,文字 5 可能是用户的拼写错误 - 或者它可能是一个字符串,而不是一个整数。因此,为了保持在面向对象编程中使用之前必须声明变量以防止拼写错误(以及许多其他优点)的好处(即使它是隐式的,如自动装箱),5 没有自动装箱。

【讨论】:

    【解决方案5】:

    以下是对不同比较的一些解读: http://www.leepoint.net/notes-java/data/expressions/22compareobjects.html

    不确定拒绝int是否是内置设计

    如果你这样做了

    Integer s=5;
    Integer d=5;
    if(d.equals(s)){
        System.out.println("Fun");
    }
    

    效果很好。

    【讨论】:

      【解决方案6】:

      int 是一种原始类型,它本身不支持任何方法。要比较 2 个ints,您只需使用== 约定,如下所示:

      if(a == b) 
      

      有一个 Integer 类是 int 的包装器,它支持一些其他方法调用

      编辑:

      根据您想要与 Integer 进行比较的编辑,但问题是文字 5 不是 Integer 您必须为其创建一个新整数。

      Integer myInt = 5;
      if(myInt.equals(someOtherInteger)) ...
      

      这种设计是由于原语没有任何方法这一事实所固有的。关于原语是否应该支持方法(或根本不存在)是关于 Java 是否是纯面向对象语言的争论的组成部分(由于原语存在,许多人说不)。

      【讨论】:

      • 我没有意识到我需要通过添加“我不是一个完全的白痴”来澄清我的问题,但我会的。这不是我要找的。​​span>
      • 那你在问什么。原语没有方法。
      猜你喜欢
      • 1970-01-01
      • 2011-01-19
      • 2014-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多