起
System.out.println(“内容”);是一条普通的输出语句,而它又经历了哪些过程呢,是如何完成的呢,于是我开始以追踪的方式进行了探索。(在IDEA中用“Alt + 鼠标左键”)
这是一条普通的输出语句,输出String类型的“Wo shi fei wu!”这样一条长度为14的字符串;
public class FeiWuTest {
public static void main(String[] args) {
System.out.println("Wo shi fei wu!");
}
}
显然System.out是“类名.”的方式,而System是java.lang包下的类
于是追踪到System类中有这样一条语句:
public final static PrintStream out = null;
可知out是PrintStream类型的静态常量
然后调用PrintSream类中peintln方法
该方法有很多种不同的调用方法,由于本测试类中是以String的方式,就查看其以String为参数的那个:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
synchronized 关键字
Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍可以访问该object中的非加锁代码块。
↑百度百科解释,我啥也不会
直接进入print(x)的调用,这里x:“Wo shi fei wu!”
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
if (s == null)//false
调用write(s) 这里 s:“Wo shi fei wu!”
该方法在java.io包下的PrintSream类中
PrintStream类中的write()方法:
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
其中
private BufferedWriter textOut;
private OutputStreamWriter charOut;
ensureOpen()方法
private void ensureOpen() throws IOException {
if (out == null)
throw new IOException("Stream closed");
}
这里的out追踪到FilterOutputStream类下
protected OutputStream out;
out == null 为真???
抛出异常???
异常一坨屎的我停止了思考
下一个
textOut.write(s) 这里 s:“Wo shi fei wu!”
BufferedWriter类中没有以String为参数的方法,去其父类Writer中
public void write(String str) throws IOException {
write(str, 0, str.length());
}
此时str为这里 “Wo shi fei wu!” str.lenghth()为14
其中又调用write(“Wo shi fei wu!” , 0 , 14)
public void write(String str, int off, int len) throws IOException {
synchronized (lock) {
char cbuf[];
if (len <= WRITE_BUFFER_SIZE) {
if (writeBuffer == null) {
writeBuffer = new char[WRITE_BUFFER_SIZE];
}
cbuf = writeBuffer;
} else { // Don't permanently allocate very large buffers.
cbuf = new char[len];
}
str.getChars(off, (off + len), cbuf, 0);
write(cbuf, 0, len);
}
}
private static final int WRITE_BUFFER_SIZE = 1024;
private char[] writeBuffer;
这个write方法是先将传入的字符串如果其长度小于等于1024则创建一个char类型的数组,长度为1024,如果传入的字符串长度大于1024,则创建的是长度为该字符串长度的char数组,名为cbuf
然后执行str.getChars(0,0+14,cbuf,0)方法
该方法在String类中:
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
其中
private final char value[];
最后调用arraycopy方法
native又是一个关键字
native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。
↑别人的知识,这个方法似乎是c++的,,我是废物,啥也不会
说白了就是复制,深拷贝
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos,int length);
似乎就是将value复制到dst中来从0开始复制,复制长度为最开始我们字符串的长度而dst其实就是cbuf
猜测这里“Wo shi fei wu!”就被复制到cbuf中
然后开始执行方法write(cbuf, 0, 14);
abstract public void write(char cbuf[], int off, int len) throws IOException;
我猜测这里应该就是真正的输出操作了从0到14
查资料如下:
java.io.BufferedWriter.write(char[] cbuf, int off, int len) 方法写入字符缓冲器的一部分,从而写入器。从中开始读取字符的偏移量,len是字符缓冲区中节的长度。
行吧,姑且是一条路走到底了
开始这个
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s); //终了
textOut.flushBuffer();//开始这个
charOut.flushBuffer();
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
仍然在BufferedWriter类中
void flushBuffer() throws IOException {
synchronized (lock) {
ensureOpen();
if (nextChar == 0)
return;
out.write(cb, 0, nextChar);
nextChar = 0;
}
}
其中
private int nChars, nextChar;
private Writer out;
private char cb[];
ensureOpen就不说了上面提过,虽然没解决,但从字面上看也该就是确保这条“路径”开通了???
nextChar全程定义未赋值,应该默认为零
if (nextChar == 0)//true
直接return了
下下一个
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);//终了
textOut.flushBuffer();//终了
charOut.flushBuffer();//开始这个
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
进入java.io包下的OutputStreamWriter类
void flushBuffer() throws IOException {
se.flushBuffer();
}
其中
private final StreamEncoder se;
进入flushBuffer()方法
弹出一个我看不懂的框
不道啥,直接没理
public void flushBuffer() throws java.io.IOException { /* compiled code */ }
这是一个sun.nio.cs包下的StreamEncoder类
构造方法???然后??
我死了
至于这个if是这样的
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);
textOut.flushBuffer();
charOut.flushBuffer();//这个if↓
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
private final boolean autoFlush;
这个final修饰的boolean也没有赋值,本废物搞不清是true还是false
至于里面的方法调用
首先out是这样的
protected OutputStream out;
在FilterOutputStream包中io包下
flush方法自然也是OutputStream类中,是上类的父类
public void flush() throws IOException {
}
之后的catch就是捕获异常了
最开始的那个println方法中还有一个newLine方法
看字面应该就是新的一行,即换行 了吧
总之以上就是慢慢摸的结果,,不知道对不对,我觉得关键性的输出还是在第一个write方法中实现的,
先这样再那样最后这样地就把“Wo shi fei wu!”给输出出来了
“C:\Program Files\Java\jdk1.8.0_271\bin\java.exe”
Wo shi fei wu!
Process finished with exit code 0
flush方法自然也是OutputStream类中,是上类的父类
public void flush() throws IOException {
}
[
之后的catch就是捕获异常了
最开始的那个println方法中还有一个newLine方法
看字面应该就是新的一行,即换行 了吧
总之以上就是慢慢摸的结果,,不知道对不对,我觉得关键性的输出还是在第一个write方法中实现的,
先这样再那样最后这样地就把“Wo shi fei wu!”给输出出来了
“C:\Program Files\Java\jdk1.8.0_271\bin\java.exe”
Wo shi fei wu!
Process finished with exit code 0
害,我懂个 der Java