深入理解 Java HelloWorld


Java 的 Hello World 代码


public class HelloWorld {
 
    /**
     * 
     * @param args
     */
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("Hello World");
    }
 
}


编译运行

$ javac HelloWorld.java 
$ java HelloWorld       
Hello World

功能就是在控制台打印 Hello World 字符串, 我们这里深入每一个步骤,探讨是如何将字符串打印到控制台的。

环境

我们刚才的程序运行在 Ubuntu Linux 的控制台 bash 程序里。 javac 是编译器, java 运行虚拟机,载入 HelloWorld.class 执行 HelloWorld 类的 main 函数,这部分是属于虚拟机的内容,暂时不做考虑,我们主要从代码调用的步骤分析。

System 类

从代码逻辑上,我们很容易看出是 System 类的 out 成员 println 函数执行了打印操作:

public final class System {

    /**
     * Default input stream.
     */
    public static final InputStream in;

    /**
     * Default output stream.
     */
    public static final PrintStream out;

    /**
     * Default error output stream.
     */
    public static final PrintStream err;

    private static final String lineSeparator;
    private static Properties systemProperties;

    static {
        err = new PrintStream(new FileOutputStream(FileDescriptor.err));
        out = new PrintStream(new FileOutputStream(FileDescriptor.out));
        in = new BufferedInputStream(new FileInputStream(FileDescriptor.in));
        lineSeparator = System.getProperty("line.separator");
    }


out 是个 PrintStream

PrintStream 类

    /**
     * Prints a string followed by a newline. The string is converted to an array of bytes using
     * the encoding chosen during the construction of this stream. The bytes are
     * then written to the target stream with {@code write(int)}.
     *
     * <p>If an I/O error occurs, this stream's error state is set to {@code true}.
     *
     * @param str
     *            the string to print to the target stream.
     * @see #write(int)
     */
    public synchronized void println(String str) {
        print(str);
        newline();
    }

具体的工作交给了 print ,  我们在这个类里面可以看到 newline 只是打印了两个特殊字符,换行。

    public synchronized void print(String str) {
        if (out == null) {
            setError();
            return;
        }
        if (str == null) {
            print("null");
            return;
        }

        try {
            if (encoding == null) {
                write(str.getBytes());
            } else {
                write(str.getBytes(encoding));
            }
        } catch (IOException e) {
            setError();
        }
    }

进一步的工作由 write 函数完成:
    public synchronized void write(int oneByte) {
        if (out == null) {
            setError();
            return;
        }
        try {
            out.write(oneByte);
            int b = oneByte & 0xFF;
            // 0x0A is ASCII newline, 0x15 is EBCDIC newline.
            boolean isNewline = b == 0x0A || b == 0x15;
            if (autoFlush && isNewline) {
                flush();
            }
        } catch (IOException e) {
            setError();
        }
    }

又来了个 out 这个,out 是 来自 OutputStream 的实现类 public class FileOutputStream extends OutputStream 

public class FileOutputStream extends OutputStream {

    private FileDescriptor fd;
    private final boolean shouldClose;

    /** The unique file channel. Lazily initialized because it's rarely needed. */
    private FileChannel channel;

    /** File access mode */
    private final int mode;

    private final CloseGuard guard = CloseGuard.get();

FileDescriptor

public final class FileDescriptor {

    /**
     * Corresponds to {@code stdin}.
     */
    public static final FileDescriptor in = new FileDescriptor();

    /**
     * Corresponds to {@code stdout}.
     */
    public static final FileDescriptor out = new FileDescriptor();

    /**
     * Corresponds to {@code stderr}.
     */
    public static final FileDescriptor err = new FileDescriptor();

    /**
     * The Unix file descriptor backing this FileDescriptor.
     * A value of -1 indicates that this FileDescriptor is invalid.
     */
    private int descriptor = -1;

    static {
        in.descriptor = STDIN_FILENO;
        out.descriptor = STDOUT_FILENO;
        err.descriptor = STDERR_FILENO;
    }

这里来到 STDOUT_FILENO, 该变量定义在: 在<stdio.h>。
STDIN_FILENO等是文件描述符,是非负整数,一般定义为0, 1, 2,属于没有buffer的I/O,直接调用系统调用,在<unistd.h>。
参考i: http://blog.csdn.net/xiaoxi2xin/article/details/5524769
    @Override
    public void write(byte[] buffer, int byteOffset, int byteCount) throws IOException {
        IoBridge.write(fd, buffer, byteOffset, byteCount);
    }

    @Override
    public void write(int oneByte) throws IOException {
        write(new 

最后是调用 os 的 write


深入理解 Java HelloWorld,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。