1. 程式人生 > 其它 >Java面試官:開發過程中

Java面試官:開發過程中

Java面試官:開發過程中

public int read() throws IOException {
return in.read();
}

public int read(byte b[]) throws IOException {
    return read(b, 0, b.length);
}

public int read(byte b[], int off, int len) throws IOException {
    return in.read(b, off, len);
}

public long skip(long n) throws IOException {
    return in.skip(n);
}

public int available() throws IOException {
    return in.available();
}

public void close() throws IOException {
    in.close();
}

public synchronized void mark(int readlimit) {
    in.mark(readlimit);
}

public synchronized void reset() throws IOException {
    in.reset();
}

public boolean markSupported() {
    return in.markSupported();
}

}


所以正如其名,FilterInputStream 就像是內部 InputStream 物件的一個過濾器一般,所有方法呼叫都需要經過一層包裝方法的『過濾』才能到達內部物件。FilterInputStream 並沒有邏輯實現,具體實現需要子類覆寫相關方法實現。

比較有意思的實現有以下幾個:

*   **BufferedInputStream**

    > BufferedInputStream 內部使用一個 buf 位元組陣列進行緩衝,覆寫了 FilterInputStream 的全部方法實現一個帶緩衝區的位元組流類。在進行磁碟或網路IO時,原始的InputStream對資料讀取的過程都是一個位元組一個位元組操作的,而BufferedInputStream在其內部提供了一個buffer,在讀資料時,會一次讀取一大塊資料到buffer中,這樣比單位元組的操作效率要高的多,特別是程序磁碟IO和對大量資料進行讀寫的時候,能提升IO效能。

*   **PushbackInputStream**

    > PushbackInputStream 內部同樣使用一個 buf 位元組陣列對已讀資料進行快取,然後可以通過 unread 方法將已讀的資料重新放回 buf 陣列,從而實現了一個支援 push back 的位元組流類。

*   **DataInputStream**

    > DataInputStream 提供了許多可以讀取 Java 基本型別的方法。

#### ByteArrayInputStream

ByteArrayInputStream 支援從 byte 陣列讀取資料,通過建構函式可以指定該 byte 陣列:

protected byte buf[];

protected int pos;

protected int mark = 0;

protected int count;

public ByteArrayInputStream(byte buf[]) {
    this.buf = buf;
    this.pos = 0;
    this.count = buf.length;
}

public ByteArrayInputStream(byte buf[], int offset, int length) {
    this.buf = buf;
    this.pos = offset;
    this.count = Math.min(offset + length, buf.length);
    this.mark = offset;
}

#### ObjectInputStream

ObjectInputStream 與 DataInputStream 類似也支援 Java 基本型別的讀取,此外還支援反序列化讀取物件。它常常與 ObjectOutputStream 搭配使用。因此,ObjectOutputStream 實現將基本型別或者物件序列化並輸出到 IO 位元組流或者裝置上,而 ObjectInputStream 從 IO 位元組流或者裝置上反序列化讀取基本型別或者物件。

比如,從檔案中讀取一個 person 物件。

ObjectInputStream input = new ObjectInputStream(new FileInputStream("data.txt"));
Person person = (MyClass) input.readObject();
input.close();


這裡要求 Person 一定要實現 java.io.Serializable 介面。

#### PipedInputStream

PipedInputStream 通常和 PipedOutputStream 搭配使用,實現了一個承載位元組流的管道類。PipedOutputStream 的輸出會自動呼叫 PipedInputStream 的 receive 方法作為輸入。PipedInputStream 提供了以下幾個特殊方法:

// 連線 PipedOutputStream 物件,形成管道
public void connect(PipedOutputStream src) throws IOException;
// 接收一個位元組
protected synchronized void receive(int b) throws IOException;
// 接收一個位元組陣列
synchronized void receive(byte b[], int off, int len) throws IOException;


注意到其 read 方法和 receive 都是同步方法,read 方法在沒有資料的時候會發生阻塞,而 receive 方法在緩衝陣列沒有剩餘空間的時候也會發生阻塞:

public synchronized int read() throws IOException {
if (!connected) {
throw new IOException("Pipe not connected");
} else if (closedByReader) {
throw new IOException("Pipe closed");
} else if (writeSide != null && !writeSide.isAlive()
&& !closedByWriter && (in < 0)) {
throw new IOException("Write end dead");
}

    readSide = Thread.currentThread();
    int trials = 2;
    while (in < 0) {
        // in小於0表示緩衝陣列為空,處於無資料狀態
        if (closedByWriter) {
            /* closed by writer, return EOF */
            return -1;
        }
        if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
            throw new IOException("Pipe broken");
        }
        /* might be a writer waiting */
        notifyAll();
        try {
            // 阻塞等待
            wait(1000);
        } catch (InterruptedException ex) {
            throw new java.io.InterruptedIOException();
        }
    }
    int ret = buffer[out++] & 0xFF;
    if (out >= buffer.length) {
        out = 0;
    }
    if (in == out) {
        /* now empty */
        in = -1;
    }

    return ret;
}

protected synchronized void receive(int b) throws IOException {
checkStateForReceive();
writeSide = Thread.currentThread();
if (in == out)
// 當in等於out,意味著緩衝陣列已滿,阻塞等待空間釋放
awaitSpace();
if (in < 0) {
in = 0;
out = 0;
}
buffer[in++] = (byte)(b & 0xFF);
if (in >= buffer.length) {
in = 0;
}
}


#### SequenceInputStream

SequenceInputStream 支援將多個 InputStream 組合起來,並按照順序進行讀取。

### OutputStream

OutputStream 與 InputStream 相對應,實現上存在很多相似之處。先看看內部方法:

public abstract class OutputStream implements Closeable, Flushable {
public abstract void write(int b) throws IOException;
public void write(byte b[]) throws IOException {//}
public void write(byte b[], int off, int len) throws IOException {/
/}
public void flush() throws IOException {//}
public void close() throws IOException {/
/}
}


OutputStream 實現了 Closeable 介面和 Flushable 方法,同樣有一個抽象的 write 方法需要實現。其他方法提供框架性程式碼,也需要實現類覆寫相關方法,提供更多的自定義功能。

#### FileOutputStream

實現上與 FileInputStream 類似,提供對檔案寫入位元組流的功能。

#### FilterOutputStream

與 FilterInputStream 類似,對 OutputStream 物件進行包裝,並繼承了 OutputStream 並覆寫全部方法,方法內容都是簡單地呼叫內部的 OutputStream 物件。

同樣的也有幾個子類實現:

*   **BufferedOutputStream**:帶緩衝區的位元組流輸出類,與 BufferedInputStream 對應;
*   **DataOutputStream**:提供寫 Java 基本型別相關方法的位元組流類,與 DataInputStream 對應;
*   **PrintStream**:與 DataOutputStream 有些類似,不過它提供了更加豐富的寫出方法,並且支援換行輸出。

#### ByteArrayOutputStream

與 ByteArrayInputStream 相反,ByteArrayOutputStream 實現輸出到內部的快取位元組陣列 buf 中。特有的方法有:

/** 將該 Stream 輸出為 byte 陣列/
public synchronized byte toByteArray()[] {
return Arrays.copyOf(buf, count);
}
/
將該 Stream 輸出到另一個 Stream 上**/
public synchronized void writeTo(OutputStream out) throws IOException {
out.write(buf, 0, count);
}


#### ObjectOutputStream

與 ObjectInputStream 對應,ObjectOutputStream 實現將 Java 基本型別資料或者 Java 物件序列化後寫入輸出位元組流中。

#### PipedOutputStream

與 PipedInputStream 搭配使用,PipedOutputStream 會輸出位元組流到管道另一端的 PipedInputStream。

## 字元流

位元組流處理的是 byte 陣列,而字元流處理的是 char 陣列。而且字元流相關的類都以 Reader 或者 Writer 為字尾。

### Reader

先看看內部方法:

public abstract class Reader implements Readable, Closeable {
public int read(java.nio.CharBuffer target) throws IOException;
public int read() throws IOException;
public int read(char cbuf[]) throws IOException;
abstract public int read(char cbuf[], int off, int len) throws IOException;
public long skip(long n) throws IOException;
public boolean ready() throws IOException;
public boolean markSupported();
public void mark(int readAheadLimit) throws IOException;
public void reset() throws IOException;
abstract public void close() throws IOException;
}


內部方法與 InputStream 非常相似,同樣實現類需要實現 read 方法。

#### BufferedReader

帶緩衝區的 Reader 實現。

#### CharArrayReader

從字元陣列讀取資料的 Reader 實現。

#### InputStreamReader

InputStreamReader 是一個包裝類,內部物件是 StreamDecoder。StreamDecoder 支援從 InputStream 中讀取字元。

public class InputStreamReader extends Reader {

private final StreamDecoder sd;

/**
 * Creates an InputStreamReader that uses the default charset.
 *
 * @param  in   An InputStream
 */
public InputStreamReader(InputStream in) {
    super(in);
    try {
        sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
    } catch (UnsupportedEncodingException e) {
        // The default encoding should always be available
        throw new Error(e);
    }
}

最後

做任何事情都要用心,要非常關注細節。看起來不起眼的、繁瑣的工作做透了會有意想不到的價值。
當然要想成為一個技術大牛也需要一定的思想格局,思想決定未來你要往哪個方向去走, 建議多看一些人生規劃方面的書籍,多學習名人的思想格局,未來你的路會走的更遠。

更多的技術點思維導圖我已經做了一個整理,涵蓋了當下網際網路最流行99%的技術點,在這裡我將這份導圖分享出來,以及為金九銀十準備的一整套面試體系,上到集合,下到分散式微服務

如何獲得這套優質的資料呢?

Java面試精選題、架構實戰文件傳送門:戳這裡免費領取