好程式設計師Java教程之Java面試寶典Java IO篇

好程式設計師發表於2020-04-18

  好程式設計師 Java 教程之 Java 面試寶典 Java IO 很多同學想知道企業在招聘Java 工程師時會提問哪些問題, 好程式設計師 Java 培訓彙總歷屆學員求職經驗並與企業溝通之後總結出《 Java 面試寶典》,涵蓋 Java 基礎、設計模式以及 Java 框架等考察點,一碼當先,學員月薪過萬不是夢 !

   1.IO 裡面的常見類,位元組流、字元流、介面、實現類、方法阻塞 ?

  輸入流就是從外部檔案輸入到記憶體,輸出流主要是從記憶體輸出到檔案。

  IO 裡面常見的類,第一印象就只知道 IO 流中有很多類, IO 流主要分為字元流和位元組流。字元流中有抽象類 InputStream OutputStream ,它們的子類 FileInputStream FileOutputStream,BufferedOutputStream 等。字元流 BufferedReader Writer 等。都實現了 Closeable, Flushable, Appendable 這些介面。程式中的輸入輸出都是以流的形式儲存的,流中儲存的實際上全都是位元組檔案。

  java 中的阻塞式方法是指在程式呼叫改方法時,必須等待輸入資料可用或者檢測到輸入結束或者丟擲異常,否則程式會一直停留在該語句上,不會執行下面的語句。比如 read() readLine() 方法。

   2. 談談對 NIO 的認知 ?

  對於NIO ,它是非阻塞式,核心類:

  1.Buffer 為所有的原始型別提供 (Buffer) 快取支援。

  2.Charset 字符集編碼解碼解決方案

  3.Channel 一個新的原始 I/O 抽象,用於讀寫 Buffer 型別,通道可以認為是一種連線,可以是到特定裝置,程式或者是網路的連線。

   3. 位元組流和字元流的區別 ?

  字元流和位元組流的使用非常相似,但是實際上位元組流的操作不會經過緩衝區( 記憶體 ) 而是直接操作文字本身的,而字元流的操作會先經過緩衝區 ( 記憶體 ) 然後透過緩衝區再操作檔案

  以位元組為單位輸入輸出資料,位元組流按照8 位傳輸

  以字元為單位輸入輸出資料,字元流按照16 位傳輸

   4.NIO 和傳統的 IO 有什麼區別 ?

  1 、傳統 IO 一般是一個執行緒等待連線,連線過來之後分配給 processor 執行緒, processor 執行緒與通道連線後如果通道沒有資料過來就會阻塞 ( 執行緒被動掛起 ) 不能做別的事情。 NIO 則不同,首先,在 selector 執行緒輪詢的過程中就已經過濾掉了不感興趣的事件,其次,在 processor 處理感興趣事件的 read write 都是非阻塞操作即直接返回的,執行緒沒有被掛起。

  2 、傳統 io 的管道是單向的, nio 的管道是雙向的。

  3 、兩者都是同步的,也就是 java 程式親力親為的去讀寫資料,不管傳統 io 還是 nio 都需要 read write 方法,這些都是 java 程式呼叫的而不是系統幫我們呼叫的, nio2.0 裡這點得到了改觀,即使用非同步非阻塞 AsynchronousXXX 四個類來處理。

   5.BIO NIO AIO 的區別以及應用場景 ?

  同步:java 自己去處理 io

  非同步:java io 交給作業系統去處理,告訴快取區大小,處理完成回撥。

  阻塞:使用阻塞IO 時, Java 呼叫會一直阻塞到讀寫完成才返回。

  非阻塞:使用非阻塞IO 時,如果不能立馬讀寫, Java 呼叫會馬上返回,當 IO 事件分發器通知可讀寫時在進行讀寫,不斷迴圈直到讀寫完成。

  BIO :同步並阻塞,伺服器的實現模式是一個連線一個執行緒,這樣的模式很明顯的一個缺陷是:由於客戶端連線數與伺服器執行緒數成正比關係,可能造成不必要的執行緒開銷,嚴重的還將導致伺服器記憶體溢位。當然,這種情況可以透過執行緒池機制改善,但並不能從本質上消除這個弊端。

  NIO :在 JDK1.4 以前, Java IO 模型一直是 BIO ,但從 JDK1.4 開始, JDK 引入的新的 IO 模型 NIO ,它是同步非阻塞的。而伺服器的實現模式是多個請求一個執行緒,即請求會註冊到多路複用器 Selector 上,多路複用器輪詢到連線有 IO 請求時才啟動一個執行緒處理。

  AIO JDK1.7 釋出了 NIO2.0 ,這就是真正意義上的非同步非阻塞,伺服器的實現模式為多個有效請求一個執行緒,客戶端的 IO 請求都是由 OS 先完成再通知伺服器應用去啟動執行緒處理 ( 回撥 )

  應用場景:併發連線數不多時採用BIO ,因為它程式設計和除錯都非常簡單,但如果涉及到高併發的情況,應選擇 NIO AIO ,更好的建議是採用成熟的網路通訊框架 Netty

   6. 什麼是 Java 序列化,如何實現 Java 序列化 ?

  序列化就是一種用來處理物件流的機制,將物件的內容進行流化。可以對流化後的物件進行讀寫操作,可以將流化後的物件傳輸於網路之間。序列化是為了解決在物件流讀寫操作時所引發的問題

  序列化的實現:將需要被序列化的類實現Serialize 介面,沒有需要實現的方法,此介面只是為了標註物件可被序列化的,然後使用一個輸出流 ( 如: FileOutputStream) 來構造一個 ObjectOutputStream( 物件流 ) 物件,再使用 ObjectOutputStream 物件的 write(Object obj) 方法就可以將引數 obj 的物件寫出

   7.PrintStream BufferedWriter PrintWriter 的比較 ?

  PrintStream 類的輸出功能非常強大,通常如果需要輸出文字內容,都應該將輸出流包裝成 PrintStream 後進行輸出。它還提供其他兩項功能。與其他輸出流不同, PrintStream 永遠不會丟擲 IOException; 而是,異常情況僅設定可透過 checkError 方法測試的內部標誌。另外,為了自動重新整理,可以建立一個 PrintStream

  2 BufferedWriter: 將文字寫入字元輸出流,緩衝各個字元從而提供單個字元,陣列和字串的高效寫入。透過 write() 方法可以將獲取到的字元輸出,然後透過 newLine() 進行換行操作。 BufferedWriter 中的字元流必須透過呼叫 flush 方法才能將其刷出去。並且 BufferedWriter 只能對字元流進行操作。如果要對位元組流操作,則使用 BufferedInputStream

  3 PrintWriter println 方法自動新增換行,不會拋異常,若關心異常,需要呼叫 checkError 方法看是否有異常發生, PrintWriter 構造方法可指定引數,實現自動重新整理快取 (autoflush)

   8. 什麼是節點流,什麼是處理流,各有什麼好處,處理流的建立有什麼特徵 ?

  節點流 直接與資料來源相連,用於輸入或者輸出

  處理流:在節點流的基礎上對之進行加工,進行一些功能的擴充套件

  處理流的構造器必須要 傳入節點流的子類

   9. 什麼是 IO ?

  它是一種資料的流從源頭流到目的地。比如檔案複製,輸入流和輸出流都包括了。輸入流從檔案中讀取資料儲存到程式(process) 中,輸出流從程式中讀取資料然後寫入到目標檔案。

   10. 有哪些可用的 Filter ?

  在java.io 包中主要由 4 個可用的 filter Stream 。兩個位元組 filter stream ,兩個字元 filter stream. 分別是 FilterInputStream, FilterOutputStream, FilterReader and FilterWriter. 這些類是抽象類,不能被例項化的。

   11.Java 中有幾種型別的流 ?

  按照流的方向:輸入流(inputStream) 和輸出流 (outputStream)

  按照實現功能分:節點流( 可以從或向一個特定的地方 ( 節點 ) 讀寫資料。如 FileReader) 和處理流 ( 是對一個已存在的流的連線和封裝,透過所封裝的流的功能呼叫實現資料讀寫。如 BufferedReader 。處理流的構造方法總是要帶一個其他的流物件做引數。一個流物件經過其他流的多次包裝,稱為流的連結。 )

  按照處理資料的單位: 位元組流和字元流。位元組流繼承於 InputStream OutputStream , 字元流繼承於 InputStreamReader OutputStreamWriter

   12. 如何實現物件克隆 ?

  有兩種方式:

  1). 實現 Cloneable 介面並重寫 Object 類中的 clone() 方法 ;

  2). 實現 Serializable 介面,透過物件的序列化和反序列化實現克隆,可以實現真正的深度克隆

   13. 什麼是緩衝區 ? 有什麼作用 ?

  緩衝區就是一段特殊的記憶體區域,很多情況下當程式需要頻繁地操作一個資源( 如檔案或資料庫 ) 則效能會很低,所以為了提升效能就可以將一部分資料暫時讀寫到快取區,以後直接從此區域中讀寫資料即可,這樣就可以顯著的提升效能。

  對於 Java 字元流的操作都是在緩衝區操作的,所以如果我們想在字元流操作中主動將緩衝區重新整理到檔案則可以使用 flush() 方法操作。

   14. 什麼是阻塞 IO? 什麼是非阻塞 IO?

  IO 操作包括:對硬碟的讀寫、對 socket 的讀寫以及外設的讀寫。

  當使用者執行緒發起一個IO 請求操作 ( 本文以讀請求操作為例 ) ,核心會去檢視要讀取的資料是否就緒,對於阻塞 IO 來說,如果資料沒有就緒,則會一直在那等待,直到資料就緒 ; 對於非阻塞 IO 來說,如果資料沒有就緒,則會返回一個標誌資訊告知使用者執行緒當前要讀的資料沒有就緒。當資料就緒之後,便將資料複製到使用者執行緒,這樣才完成了一個完整的 IO 讀請求操作,也就是說一個完整的 IO 讀請求操作包括兩個階段:

  1) 檢視資料是否就緒 ;

  2) 進行資料複製 ( 核心將資料複製到使用者執行緒 )

  那麼阻塞(blocking IO) 和非阻塞 (non-blocking IO) 的區別就在於第一個階段,如果資料沒有就緒,在檢視資料是否就緒的過程中是一直等待,還是直接返回一個標誌資訊。

  Java 中傳統的 IO 都是阻塞 IO ,比如透過 socket 來讀資料,呼叫 read() 方法之後,如果資料沒有就緒,當前執行緒就會一直阻塞在 read 方法呼叫那裡,直到有資料才返回 ; 而如果是非阻塞 IO 的話,當資料沒有就緒, read() 方法應該返回一個標誌資訊,告知當前執行緒資料沒有就緒,而不是一直在那裡等待。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913864/viewspace-2686928/,如需轉載,請註明出處,否則將追究法律責任。

相關文章