真正的”Hello World” 我们都知道如何在Java中写Hello World,但当我们深入探究 System类的实现时,它应该是怎样的呢?
System.out.println("Hello World!");VM会调用initPhase1方法来完成此类的初始化,与clinit分离。
java.lang.System
public final class System { private static native void registerNatives(); static { registerNatives(); }}我们跳转到initPhase1,它创建一个PrintStream对象,然后触发setOut0(PrintStream out)方法。
private static void initPhase1() { /// ... FileInputStream fdIn = new FileInputStream(FileDescriptor.in); FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err); initialIn = new BufferedInputStream(fdIn); setIn0(initialIn); // stdout/err.encoding在VM与终端关联时设置, // 因此它们等同于Console.charset(),否则这些属性的编码 // 默认为native.encoding setOut0(newPrintStream(fdOut, props.getProperty("stdout.encoding"))); setErr0(newPrintStream(fdErr, props.getProperty("stderr.encoding"))); // ...}setOut0是一个本地方法,但newPrintStream返回一个PrintStream,它有println()方法,这足以让我们理解发生了什么。
private static PrintStream newPrintStream(OutputStream out, String enc) { if (enc != null) { return new PrintStream(new BufferedOutputStream(out, 128), true, Charset.forName(enc, UTF_8.INSTANCE)); } return new PrintStream(new BufferedOutputStream(out, 128), true);}println()打印到新行,并且由于synchronized关键字具有多线程安全性。
public class PrintStream extends FilterOutputStream implements Appendable, Closeable {
public void println(boolean x) { if (getClass() == PrintStream.class) { writeln(String.valueOf(x)); } else { synchronized (this) { print(x); newLine(); } } }}最后,setOut0将PrintStream放入System的类变量中,即System.out:
public static final PrintStream out = null;就这样,我们可以通过这样写来让HelloWorld更复杂:
public class HelloWorld { public static void main(String[] args) { FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); PrintStream out = new PrintStream(new BufferedOutputStream(fdOut, 128), true); out.println("Hello World!"); }}太酷了~