在Java程序(特别是控制台)中常用System.out.println()
语句来输出信息,从开始学习Java就知道用它来输出Hello World,没有深究其实现原理,现在查阅文档、源代码后记录一下。
首先查阅文档和源码可知System
是java.lang
包里的一个final
类,而每个Java程序是默认import java.lang.*
的,因此即使程序中没有手动导入,也可访问到System
类。
main()
方法是static
修饰的,根据Java语法,它只能调用static
方法和变量,那么查看System
类的源码有public static final PrintStream out = null;
这一行,说明System.out
是public
和static
的,因此能在main()
中访问。
System.out
是一个PrintStream
类型的变量,而在PrintStream
中有多个print()
和println()
方法重载,因此可输出多种类型的数据。
继承关系如图所示,所有类都间接或直接继承Object
类。
想必还有一个疑问,就是System
类中public static final PrintStream out = null;
,那么out
变量是在哪里、什么时候初始化,从而可以直接使用的呢?因为out
是static
变量,我们通过System.out
(类名.变量名)的方式调用,再查看System
类源码可发现在static{}
代码块中调用了registerNatives()
,而native
方法registerNatives()
由C/C++实现,这里只是一个接口,在System
类第一次被加载时,调用这个方法将out
变量进行了初始化,让它指向控制台,于是就可以直接使用了。
看到这里,似乎还有println()
方法没有研究。
查看java.io
包中的PrintStream
类寻找println()
方法,可以看到有形参为boolean、char、int…等类型的println()
的重载,而println()
其实调用了print()
再调用newLine()
来实现换行。
而在不同类型形参的print()
方法中,除char[]
变量,都调用String.valueOf()
转换成String
再传递给write()
方法。
而在write()
方法中,调用textOut.write()
来输出字符串。
而textOut
是在PrintStream
中声明的BufferedWriter
类型变量。下面还有一行private OutputStreamWriter charOut;
接着看,在构造方法中,先是初始化了OutputStreamWriter
类型变量charOut
,再用它初始化textOut
。
至此可以清楚,System.out.println()
或System.out.print()
(不换行),其实最终调用了Writer
类中的write()
方法进行字符流输出,只是整个过程封装了许多方法来支持各种类型的变量、以及自动初始化等,使得用户能够方便快捷在控制台打印数据。
有不妥之处欢迎补充纠正。