我们知道,当我们在sysout(System.out.Println)语句内部使用对象时,它的toString方法会被调用。使用原语,它可以直接打印。但是当我们使用任何包装器类时,使用的是对象类型,假设Integer如下所示
Integer i = new Integer(10)
System.out.Println(i);是toString()负责打印还是拆箱?
发布于 2010-01-23 20:28:26
快速测试和调试运行表明,调用的是print(Object),而不是print(int)。
检查这一点的一个好方法是:
Integer val = null;
System.out.print(val);如果使用取消装箱,这将抛出一个NullPointerException。但是,这不会发生,它会打印字符串null,这是传入null时String.valueOf(Object)的输出。
要记住的另一个方面是,PrintStream在Java5之前就已经存在了。当Java5引入自动装箱时,必须确保使用PrintStream的任何现有代码都不会突然改变其行为。因此,任何调用print(Object)的现有代码都不能仅仅因为一个新的语言特性而突然将其行为更改为调用print(int)。必须始终保持向后兼容性。
发布于 2010-01-23 21:00:38
(...)但是当我们使用任何包装器类时,使用的是对象类型,假设Integer如下所示
Integer I=新整数(10) System.out.println(i);
是toString()负责打印还是拆箱?
您正在将一个Object传递给println,所以很明显调用的是println(Object obj),它会写入String.valueOf(obj)的输出,如果obj不是obj.toString(),则会调用null。
PS:无意冒犯,但是,你为什么不看看来源呢?
更新:我可能错过了问题的要点(如果可以的话,这个问题在目前的形式上是有误导性的)。实际上,问题可能是:
(...)但是当我们使用任何包装器类时,使用的是对象类型,假设Integer如下所示
Integer I=新整数(10) System.out.println(i);
哪个方法将被调用:println(Object)还是println(int)?
如果这就是问题所在,那么答案当然在于The Java Language Specification。为简化起见,在运行时调用的方法将是在编译时确定的方法。现在,编译器如何确定要调用的方法?好的,这在15.12 Method Invocation Expressions一节中有解释。我不会涵盖所有的细节,规范比我做得更好,但基本上,第一步是找到要搜索的类或接口,第二步是找到所有适用的方法,然后选择最具体的方法,第三步是验证所选的方法是否合适。我将重点放在第二步(这是这里有趣的一步)。如15.12.2 Compile-Time Step 2: Determine Method Signature小节所述
如果一个方法可以通过子类型(§15.12.2.2)来应用,也可以通过方法调用转换(§15.12.2.3)来应用,或者它是一个可用的可变参数方法(§15.12.2.4),则该方法是适用的。
确定适用性的过程从确定潜在适用的方法(§15.12.2.1)开始。该过程的其余部分分为三个阶段。
讨论
分阶段的目的是确保与Java编程语言的旧版本兼容。
第一阶段(§15.12.2.2)执行重载解析,不允许装箱或拆箱转换,也不允许使用可变大小方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段。
讨论
这保证了在该语言的旧版本中有效的任何调用都不会因为引入了可变参数方法、隐式装箱和/或取消装箱而被认为是模糊的。
第二阶段(§15.12.2.3)在允许装箱和拆箱的同时执行重载解析,但仍然排除了可变大小方法调用的使用。如果在此阶段没有找到适用的方法,则处理继续到第三阶段。
讨论
这确保了如果存在适用的固定大小方法,则永远不会调用可变大小方法。
第三阶段的(§15.12.2.4)允许重载与变量方法、装箱和拆箱相结合。
在泛型方法(§8.4.4)的情况下,决定一个方法是否适用将需要确定实际的类型参数。实际类型参数可以显式或隐式传递。如果它们是隐式传递的,则必须从参数表达式的类型中推断出它们是(§15.12.2.7)。
如果在适用性测试的三个阶段之一中确定了几种适用的方法,则选择最具体的方法,如§15.12.2.5部分所述。有关详细信息,请参阅以下小节。
在这种特殊情况下,println(Obj)可以通过子类型实现(而println(int)可以通过调用转换来实现,因为装箱/拆箱是一个转换(§5.3))。因此,编译器将输入phase 1。如果我们看最后一句话:
如果通过子类型找不到适用的方法,则从第2阶段(§15.12.2.3)继续搜索适用的方法。否则,通过子类型从适用的方法中选择最具体的方法 。
在这里,子类型没有任何其他方法可用,所以这是结束,将调用println(Object) (因此将调用toString(),以回答最初的问题)。
发布于 2010-01-23 20:14:34
所有这些都早于在1.5中引入的 。回答这些问题的代码--或者API文档--对于1.5+来说根本没有改变。
基本上,在行的末尾是用于非原语的toString方法,比如Integer的实例。
首先,对于基元,每个基元都有不同的处理方式。例如,对于int
打印一个整数。String.valueOf(int)生成的字符串根据平台的缺省字符编码转换为字节,这些字节完全按照write(int)方法的方式写入。
但是对于像Integer这样的对象,println调用print:
打印对象。String.valueOf(Object)方法生成的字符串根据平台的缺省字符编码转换为字节,这些字节完全按照write(int)方法的方式写入。
那么valueOf使用的是什么呢?这就是您问题的答案:对于Integer,它的toString方法被调用。这是来自String.valueOf上的文档
如果参数为null,则字符串等于"null";否则,返回obj.toString()的值。
https://stackoverflow.com/questions/2123086
复制相似问题