我们知道当我们在sysout(System.out.Println)语句中使用对象时,会调用toString方法。和原始它直接打印。但是当我们使用任何Wrapper类的对象时,请使用假设Integer,如下面的
Integer i = new Integer(10)
System.out.Println(i);
是toString()负责打印还是取消装箱?
答案 0 :(得分:10)
快速测试和调试运行显示调用了print(Object)
,而不是print(int)
。
检查这个的好方法是:
Integer val = null;
System.out.print(val);
如果使用了un-boxing,则会抛出NullPointerException。但是,这不会发生,它会打印字符串null
,这是传入null时String.valueOf(Object)
的输出。
要记住的另一个方面是在Java 5之前存在PrintStream
。当在Java 5中引入自动装箱时,必须确保使用PrintStream
的任何现有代码不会突然出现其行为改变。因此,调用print(Object)
的任何现有代码都不得突然将其行为更改为调用print(int)
,而只是因为新的语言功能。必须始终保持向后兼容性。
答案 1 :(得分:5)
(...)但是当我们使用任何Wrapper类类型时 使用对象说假设整数 喜欢以下
Integer i = new Integer(10) System.out.println(i);
是toString()负责的 打印还是取消装箱?
您正在将Object
传递给println
,因此显然println(Object obj)
会调用String.valueOf(obj)
来写The Java Language Specification的输出,如果{{{}} obj.toString()
1}}不是obj
。
更新:我可能错过了问题的重点(如果可能的话,这会误导当前的形式)。实际上,问题可能是:
(...)但是当我们使用任何Wrapper类类型时 使用对象说假设整数 喜欢以下
null
将采用何种方法:
Integer i = new Integer(10) System.out.println(i);
或println(Object)
?
如果这就是问题所在,那么答案就在于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)
确定的过程 适用性从确定开始 潜在适用的方法 (§15.12.2.2)。其余部分 过程分为三个阶段。
<强>讨论强>
分裂的目的 阶段是为了确保兼容性 旧版本的Java编程 语言。
第一阶段(§15.12.2.3) 无需执行重载决策 允许装箱或拆箱 转换,或使用变量 arity方法调用。如果不 在此期间找到适用的方法 阶段然后处理继续到 第二阶段。
<强>讨论强>
这可以保证任何调用 在旧版本中有效 语言不被认为是模棱两可的 由于引入 变量arity方法,隐含 装箱和/或拆箱。
第二阶段(§15.12.2.4) 执行重载分辨率 允许装箱和拆箱,但是 仍然排除使用变量 arity方法调用。如果不 在此期间找到适用的方法 阶段然后处理继续到 第三阶段。
<强>讨论强>
这确保了变量arity 如果一个方法永远不会被调用 存在适用的固定方法。
第三阶段(§8.4.4) 允许重载与 变量arity方法,拳击和 开箱。
确定方法是否 在适用的情况下适用 通用方法(§15.12.2.7), 要求实际的类型参数 决心。实际类型参数可以 明确地或隐含地传递。如果 他们必须隐含地通过 从中推断§15.12.2.5 参数表达式的类型。
如果有多种适用方法 其中一个被确认 适用性测试的三个阶段, 然后选择最具体的一个, 如(§5.3)部分所述。 请参阅以下小节 的信息。
在这种特殊情况下,println(int)
适用于子类型(并且println(Obj)
适用于调用转换,因为装箱/取消装箱是转化phase 1)。所以编译器将进入(§15.12.2.3)。如果我们看一下最后一句话:
如果找不到子类型适用的方法,则搜索适用的方法将继续第2阶段(§15.12.2.5)。否则,在通过子类型适用的方法中选择最具体的方法{{3}}。
这里,没有任何其他适用于子类型的方法,所以这就是结束,println(int)
将被调用(因此println(Object)
将被调用,以回答初始问题)。
答案 2 :(得分:4)
所有这些都早于1.5中引入的autoboxing。回答这些问题的代码 - 或API文档 - 在1.5+时根本没有变化。
基本上,在行的末尾是非基元的toString
方法,例如Integer
的实例。
首先,对于原始人来说,每个人都有不同的待遇。例如,对于int
,
打印整数。产生的字符串 by String.valueOf(int)已翻译 根据平台的字节数 默认字符编码,以及这些 字节完全写入 write(int)方法的方式。
但对于像Integer
这样的对象,println调用print,其中:
打印对象。产生的字符串 通过String.valueOf(Object)方法 被翻译成字节 平台的默认字符 编码,并写入这些字节 完全按照的方式 write(int)方法。
那么valueOf
使用什么?这是您的问题的答案:对于Integer
,调用其toString
方法。这来自String.valueOf
如果参数为null,则为字符串 等于“null”;否则,价值 返回obj.toString()。