找回密码
 立即注册
首页 业界区 安全 `System.out.println(Object)` 的打印行为详解

`System.out.println(Object)` 的打印行为详解

全阳霁 4 天前
System.out.println(Object) 是 Java 中最常用的输出方法之一,它的行为等同于 java.io.PrintStream#println(Object),因为 System.out 是一个 PrintStream 实例。
  1. package java.lang;
  2. public final class System {
  3.     /**
  4.      * The "standard" output stream. This stream is already
  5.      * open and ready to accept output data. Typically this stream
  6.      * corresponds to display output or another output destination
  7.      * specified by the host environment or user.
  8.      * <p>
  9.      * For simple stand-alone Java applications, a typical way to write
  10.      * a line of output data is:
  11.      * <blockquote><pre>
  12.      *     System.out.println(data)
  13.      * </pre></blockquote>
  14.      * <p>
  15.      * See the println methods in class PrintStream.
  16.      *
  17.      * @see     java.io.PrintStream#println()
  18.      * @see     java.io.PrintStream#println(boolean)
  19.      * @see     java.io.PrintStream#println(char)
  20.      * @see     java.io.PrintStream#println(char[])
  21.      * @see     java.io.PrintStream#println(double)
  22.      * @see     java.io.PrintStream#println(float)
  23.      * @see     java.io.PrintStream#println(int)
  24.      * @see     java.io.PrintStream#println(long)
  25.      * @see     java.io.PrintStream#println(java.lang.Object)
  26.      * @see     java.io.PrintStream#println(java.lang.String)
  27.      */
  28.     public final static PrintStream out = null;
  29. }
复制代码
java.io.PrintStream#println(Object) 方法会打印对象的 字符串表示形式,其行为由 Java 语言规范定义,具体实现如下:
  1. // class java.io.PrintStream
  2. public void println(Object x) {
  3.     String s = String.valueOf(x); // 关键转换
  4.     synchronized (this) {
  5.         print(s);
  6.         newLine(); // 添加换行符
  7.     }
  8. }
复制代码
其中,java.lang.String#valueOf(Object) 描述了对象转字符串的机制。
  1. // class java.lang.String
  2. public static String valueOf(Object obj) {
  3.     return (obj == null) ? "null" : obj.toString();
  4. }
复制代码
继续来看Object.toString方法,该方法返回一个类名@十六进制哈希码串。见如下java源码:
  1. // class java.lang.Object
  2. /**
  3. * Returns a string representation of the object. In general, the
  4. * {@code toString} method returns a string that
  5. * "textually represents" this object. The result should
  6. * be a concise but informative representation that is easy for a
  7. * person to read.
  8. * It is recommended that all subclasses override this method.
  9. * <p>
  10. * The {@code toString} method for class {@code Object}
  11. * returns a string consisting of the name of the class of which the
  12. * object is an instance, the at-sign character `{@code @}', and
  13. * the unsigned hexadecimal representation of the hash code of the
  14. * object. In other words, this method returns a string equal to the
  15. * value of:
  16. * <blockquote>
  17. * <pre>
  18. * getClass().getName() + '@' + Integer.toHexString(hashCode())
  19. * </pre></blockquote>
  20. *
  21. * @return  a string representation of the object.
  22. */
  23. public String toString() {
  24.     return getClass().getName() + "@" + Integer.toHexString(hashCode());
  25. }
复制代码
示例代码演示


  • 下面是默认打印方式
  1. // 普通对象(未重写 toString)
  2. Object obj = new Object();
  3. System.out.println(obj);   // 输出: java.lang.Object@6d06d69c
复制代码

  • 如果需要友好打印,可以重新 toString 方法
  1. // 重写 toString 的对象
  2. class Person {
  3.     String name;
  4.     Person(String name) { this.name = name; }
  5.     @Override
  6.     public String toString() { return "Person: " + name; }
  7. }
  8. System.out.println(new Person("Alice")); // 输出: Person: Alice
复制代码

  • 关于 lombok的 @ToString 注解
lombok工具会为class类生成 toString 方法。见下方示例:
  1. @ToString
  2. public class Person {
  3.     int age;
  4.     String name;
  5.    
  6.     Person(String name) { this.name = name; }
  7. }
  8. // 上面class经过IDE build以后,会生成如下代码中的 toString方法
  9. public class Person {
  10.     int age;
  11.     String name;
  12.     Person(String name) {
  13.         this.name = name;
  14.     }
  15.     public String toString() {
  16.         return "Person(age=" + this.age + ", name=" + this.name + ")";
  17.     }
  18. }
复制代码


anyway,生产环境要严谨使用System.out.println来打印对象,PrintStream是同步的,会影响程序性能,尤其是多线程环境下会成为性能瓶颈。相比之下,我们借助更具优势的日志框架,例如SLF4J+Logback组合,来实现程序日志的打印。
日志框架的优势:


  • 异步输出:通过AsyncAppender实现非阻塞日志
  • 级别控制:动态调整日志级别(TRACE/DEBUG/INFO/WARN/ERROR)
  • 性能优化:使用占位符延迟字符串构建
  • 格式定制:自定义日志格式(时间戳、线程ID等)

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册