天天看點

Java SE 學習筆記 第十記

2012-07-30

1、裝飾模式:又叫包裝模式,能夠在不創造更多子類的情況下動态地将對象的功能加以擴充,是繼承的一種替代方案。一個類對象裝飾另一個類對象,就可以以裝飾對象的方法處理被裝飾對象,而整個處理過程對用戶端是透明的,實際的過程是裝飾對象的處理方法調用被裝飾對象的處理方法,并在被裝飾對象的處理方法上添加新的功能,也就是說最終是把用戶端的調用委托到被裝飾類。這種模式的好處就是在不造成類數量增加的情況下,構造更多功能的對象。

2、裝飾模式與繼承的差別:裝飾模式用來擴充特定對象的功能,并且是動态的,在運作時配置設定添加的職責,是以靈活性比較好;而繼承是擴充類的功能,一旦擴充就不能修改,是靜态的,在編譯時配置設定添加的職責,是以靈活性比較差。另外,一個規定的對象同時能被對個裝飾對象裝飾,用戶端可以通過選擇合适的裝飾對象操作被裝飾對象。

3、裝飾模式的角色:

    1)抽象建構角色(Component):一般是一個抽象類或者接口,用來規範被裝飾對象的結構。如:InputStream和OutputStream。

    2)具體建構角色(Concrete Component):也就是真實對象,繼承或實作了抽象建構角色。如:節點流FileInputStream和FileOutputStream。

    3)裝飾角色(Decorator):繼承或實作抽象建構角色的抽象類或者接口或者類,以實作用戶端對象可以使用和具體建構角色相同的方式與裝飾對象進行互動。裝飾角色接收用戶端對象的所有請求,裝飾角色内部持有一個抽象建構角色的引用變量,通過這個引用才能最終将用戶端的請求轉發給建構角色,由建構角色去完成。如:過濾流FilterInputStream和FileOutputStream。

    4)具體裝飾角色(Concrete Decorator):繼承或實作抽象裝飾角色的類,具體實作對被裝飾對象的附加功能添加在這個類中,而不是裝飾角色中。如:過濾流DataInputStream和DataOutputStream。

4、new DataInputStream(new BufferedInputStream(new FileInputStream(“C:\test.text”)));

5、Java中采用Unicode字元,一個字元16位,字元流Reader和Wrider處理的都是Unicode字元,一次至少兩個位元組16位。

6、InputStreamReader直接繼承Reader,是位元組流通向字元流的橋梁。構造方法有InputStreamReader(InputStream in)、InputStreamReader(InputStream in,String cs)等,用于接收一個InputStream對象,并使用cs編碼格式編碼,如果沒有cs參數則使用系統預設編碼格式。類中提供了getEncoding()方法可以傳回該流使用的字元編碼格式名稱。可以将InputStreamReader看做是把InputStream裝飾成處理字元流的過濾流。

7、OutputStreamWriter直接繼承Writer,是位元組通向字元流的橋梁。構造方法有OutputStreamWriter(OutputStream out)、OutputStreamWriter(OutputStream out,String cs)等,用于接收一個OutputStream對象,并使用cs格式編碼,如果沒有cs參數則使用系統預設的編碼格式編碼。類中提供了getEncoding()方法可以傳回該流使用的字元編碼格式名稱。flush()方法可以強制重新整理該流的緩沖。可以将OutputStreamReader看做是把OutputStream裝飾成處理字元流的過濾流。由于繼承了Writer,是以繼承了其中的writer(String str)方法,可以一次寫入一個字元串。

8、BufferedReader直接繼承Reader,類比于BufferedInputStream,隻是類中的位元組緩沖數組變更為字元緩沖數組,其類中其他方法使用方式與BufferedInputStream中方法使用幾乎相同,是一個接收Reader的過濾流。類中提供了一個readLine()方法讀取Reader流中的一個文本行,并将遊标轉移到該行的行尾,如果遊标已經到行尾,則會傳回null。

9、BufferedWriter直接繼承Writer,類比于BufferedOutputStream,隻是類中的位元組緩沖數組變更為字元緩沖數組,其類中的方法使用方式與BufferedOutputStream中的方法幾乎相同,是一個接受Writer的過濾流。由于繼承了Writer,是以繼承了其中的writer(String str)方法,可以一次寫入一個字元串。

10、FileReader繼承InputStreamReader,類似于FileInputStream,隻是處理的對象是字元。

11、FileWriter繼承OutputStreamWriter,類似于FileOutputStream,隻是處理對象是字元。如果FileWriter依賴的檔案不存在則會自動建立這個檔案,如果FileWriter試圖打開一個隻讀檔案就會抛出一個IOException異常。

12、CharArrayReader繼承Reader,類似于ByteArrayInputStream,隻是位元組數組更改為字元數組。

13.CharArrayWriter繼承Writer,類似于ByteArrayOutputStream,隻是位元組數組更愛為字元數組。

14、System.in其實是一個InputStream标準輸入流,通常是從鍵盤輸入;System.out其實是一個PrintStream标準輸出流,一般是輸出到控制台。

15、String的getChars(int srcBegin,int srcEnd,char[] dst,int dstBegin)方法用于将原字元串中的srcBegin到srcEnd的字元以字元數組的方式複制到字元數組dst的dstBegin位置開始。

16、ASCII(American Standard Code for Information Interchange):美國資訊互換标準代碼,采用8位二進制位編碼,将英文中常用的字元、數字元号與最高位為0,相應十進制數為0-127的數值對應進行編碼。另外還有128個擴充ASCII編碼,其最高位為1,用于編制一些名額附後和其它符号。

17、GB2312:資訊交換用漢字編碼字元集-基本集,使用兩個位元組表示一個中文字元,并且每個位元組的最高位都是1.

18、GBK:GB2312的擴充,完全相容GB2312,并且多容納了繁體中文和一些不常用的漢字。

19.ISO-8859-1:西方國家使用的字元編碼集,屬于單位元組的字元集,其中英文隻用了其中數值小于128的部分。不相容漢字。

20、Unicode:通用字元集,可以對所有語言文字進行編碼,每個字元都使用兩個位元組,Java中采用這個編碼方式以實作字元的跨平台。這種編碼的缺點在于在internet上傳輸的效率比較低,因為一些使用一個位元組就能表示的字元也使用兩個位元組表示,高位元組填0。

21、UTF-8:不定長字元編碼方式,根據字元需要的位元組長度配置設定位元組,有些字元用一個位元組,有些兩個,有些三個。網際網路上常用這種編碼方式,傳輸效率高,字元容量大。

22、java.io.RandomAccessFile:随即通路檔案類,直接繼承Object,并實作了DataInput和DataOutput接口。構造方法有RandomAccessFile(File file,String access)或者RandomAccessFile(String name,String access),其中file或者name表示依賴的File對象或者檔案名,access表明使用檔案的方式是“r”(隻讀)還是“rw”(讀寫)。另外,由于類中包含一個long變量pos作為流的遊标,使用該類的getFilePointer()可以獲得目前遊标的位置,使用該類的seek(long pos)可以将遊标定位到pos位置,使用skipBytes(int n)可以将遊标向後移動n個位元組。由于該類實作了DataInput和DataOutput接口,是以類中提供了大量讀寫各種資料類型的方法,特别的有readUTF()和writeUFT(String str)方法以UFT的格式讀寫資料。該類的特點在于類中包含了輸入流方法和輸出流方法,相當于輸入流和輸出流的合體。

23、java.nio.Charset類中的availableCharsets()方法可以傳回一個SorteMap<String,Charset>排序映射。其中的Key為目前系統所支援的字元集名。

24、序列化/反序列化:将對象轉換為位元組流(因為對象不是字元,轉換成字元流沒有意義)儲存起來,并在以後從位元組流中還原這個對象的機制。若把一個對象序列化後儲存到永久儲存設備上,這個過程也叫做持久化。

25、聲明對象可序列化:一個對象能夠序列化的前提是對象必須實作Serializable或者Externalizable接口。其中Serializable接口隻是一個辨別性接口,接口中沒有定義任何方法,實作該接口僅是表示這個類可以被序列化而已。繼承一個可序列化的類,其子類也可序列化,即序列化特性可以被繼承。

26、被序列化的對象中如果存在其它對象的引用,則其它對象的引用也會被序列化,并且引用的對象又包含其它對象的引用也會被序列化,也就是序列化會根據對象中的引用一層一層連接配接下去序列化。

27、對象序列化的時候,如果對象中的某成員無法序列化,則會抛出NotSerializableException異常。此時,若将該無法被序列化的對象使用關鍵字transient(瞬間)修飾,則序列化的時候不會序列化該成員,對象的序列化能夠正常進行。

28、對象序列化的時候,不會序列化對象中的static變量和方法(因為它們屬于類,不屬于對象),也不會序列化被transient修飾的成員。隻會将對象中的成員變量序列化,寫入到位元組流中(通過位元組流可寫入到儲存設備上永久儲存)。如果成員變量是一個對象的引用,則會按照同樣序列化的規則序列化引用的對象,以此類推各個對象引用。

29、ObjectOutputStream類:繼承了OutputStream類,并且實作了ObjectOutput接口,ObjectOutput接口又實作了DataOutput接口。構造方法有ObjectOutputStream(OutputStream out),可接收一個輸出位元組流,是一個過濾流,主要用于實作對象的序列化。另外,由于實作了DataOutput接口,是以類中包含大量寫入各種類型資料的方法。

30、将對象序列化的方法:使用ObjectOutputStream類的writeObject(Object obj)方法。預設會将obj的類、類的簽名、以及類和其所有超類的非transient非static成員變量寫入到輸出流中,即實作了序列化。

31、ObjectInputStream類,繼承了InputStream類,并且實作了ObjectInput接口,而ObjectInput接口又實作了DataInput接口。構造方法有ObjectInputStream(InputStream in),可接收一個輸入位元組流,也是一個過濾流,主要用于實作對象的反序列化。另外,由于實作了DataInput接口,是以類中包含了大量讀取各種資料類型的方法。

32、對象反序列化的方法:使用ObjectInputStream類的readObject()方法,傳回一個Object對象。由于對象在序列化的時候儲存了對象的類資訊,是以readObject方法無需參數,就能将目前遊标所在位置後邊的對象按該對象序列化時的類資訊恢複出來。恢複的時候,并不會調用該對象類的任何構造方法,僅是根據儲存的狀态資訊在記憶體中重新建構對象而已。又由于對象序列化的時候不會序列化transient修飾的成員變量,但儲存的類資訊中存在該成員的資訊,是以反序列化後,被transient由于序列化時沒有将值儲存下來,其值隻能是其資料類型的預設值。

33、序列化和反序列化過程中,如果需要對對象進行特殊處理,不按照java提供的預設序列化和反序列化方法進行,可自定義序列化和反序列化的處理方法。方法為在需要被序列化和反序列化的類中實作兩個方法:

    1)序列化方法:private void writeObject(java.io.ObjectOutputStream stream)throws IOException{};在方法體中寫入自己的處理對象成員變量與寫入ObjectOutputStream流的代碼,當對該類對象進行序列化的時候便會調用這個方法進行序列化,不再使用預設序列化方法。

    2)反序列化方法:private void readObject(java.io.ObjectInputStream stream)throws IOException,ClassNotFoundException{};在方法體重寫入自己處理對象成員變量與ObjectInputStream流的代碼,當對該類對象進行反序列化的時候就會自動調用這個方法進行反序列化,不再使用預設的反序列化方法處理。

34、程序:程序是一個運作中的程式,每一個程式運作的時候都需要在程序中執行代碼,作業系統會為一個程式配置設定該程式程序所需要的資源,包括記憶體空間等。程序與程序之間的内部資料和狀态都是完全獨立的,是以程序與程序之間的切換代價比較高。

35、線程:每個程序至少包含一個線程,一個程序可以包含多個線程,每個線程可獨立完成程序中的一個工作,是程式内的一個順序控制流,隻能使用配置設定給程式的資源和環境。并且線程運作時隻需要很少的資源,通常隻有寄存器資料以及程式執行時的堆棧,是以線程與線程之間的切換代價比較小。同一個程序之間的線程共享一塊記憶體空間和系統資源,它們有可能會互相影響。

36、多任務處理包括基于程序和基于線程兩種對任務處理,它們都是為最大限度使用CPU資源,以提高CPU效率。

37、Java語言内置支援多線程變成,其他大多數程式設計語言都需要通過外部庫連結來實作多線程程式設計。

38、Java程式中,每當程式啟動的時候都會自動啟動一個線程,main方法就運作在這個自動啟動的主線程上,是以這個線程也叫做main thread。每個Java程式至少都有一個線程,這個線程就main線程。