好程序員Java教程之Java面試寶典Java IO篇

 好程序員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()方法應該返回一個標誌信息,告知當前線程數據沒有就緒,而不是一直在那裏等待。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章