2011年6月26日 星期日

《深入淺出 Java》筆記 (11/27更新)

一.認識JAVA的API

ArrayList會自動調整陣列大小
add():新增ArrayList元素
remove():移除ArrayList元素
indexOf():尋找某項元素的位置
isEmpty():判斷ArrayList中的某位置是否為空
size():取得ArrayList的大小


二.繼承與多型

1.繼承可以參考這篇,淺顯易懂!:
http://blog.xuite.net/andy19890411/Orz/37666000

2.如果你想知道 x 是否應該要extend y 時,可以運用IS-A來判斷。此外,子類別只能繼承一個父類別

3.你必須確認你設計的所有subclass都能通過任一個上層的superclass的IS-A測試

4.繼承下來的method可以被override,但instance variable不能被蓋過去

5.當你要overrid過superclass的method時,你必須確定:
(1)參數必須要一樣,而且回傳型別必須要相容
(2)method的存取權不得縮小

6.你可以任意的改變overload版的回傳型別,但必須確定所有的overload使用的是不同的參數。此外,更動overload版method的存取權限


三.interface 與 polymorphism

1.從ArrayList<Object>取出的物件,都會被當作是Object這個class的實體。編譯器無法將此物件識別為Object以外的事物

2.當你把物件塞進ArrayList<Object>時,不管它原來是什麼,你只能把它當作是Object

3.從ArrayList<Object>取出參考時,參考的型別只會是Object

4.編譯器是根據參考型別來判斷有哪些method可以呼叫,而不是根據物件確實的型別

5.抽象的class可以帶有抽象與非抽象的方法

6.要從改寫過的版本叫用父類別版本的方法時,則利用super關鍵字

7.抽象method的意義是就算無法實作出method的內容,但還是可以定義出一群subtype共通的協定。而這樣的好處就是多形。你可以加入新的subtype到程式中,卻又不必重寫或修改處理這些型別的程序

8.interface就像純抽象的class。所有interface的method都是抽象的,所以任何implements的class都必須實作出這些抽象的method。而interface的目的,是為了多型

9.class可以umplement多個interface

10.如果新的class無法對其他的class通過IS-A的測試時,就設計不繼承其他class的class

11.只有在需要某class的特殊化版本時,以改寫或增加新的方法來繼承現有的class

12.當需要定義一群子類別的樣板時,又不想讓某個class被初始化,就標示為abstract

13.如果想要定義出class可以扮演的角色,就使用interface



四.constructor 與 gc

1.stack:方法呼叫、使用與區域變數的存放空間

2.heap:物件的存放空間
﹡實體變數保存在所屬的物件中,位於heap上
﹡如果實體變數是個對物件的參考,則參考與物件都是在heap上

3.如果你在建構物件時,需要有程式碼幫忙初始化,那麼你就得自行撰寫建構元

4.編譯器只會在你完全沒有設定建構元時,才會自動替你建立沒有參數的建構元。如果你已經寫了一個有參數的建構元,並且你需要一個沒有參數的建構元,你就必須自己建立

5.overload的建構元必須有不同的參數,且建構元的參數必須不相同

6.對super()、this()的呼叫必須是建構元的第一個敘述句,此外,兩者不能同時叫用

7.使用this()能從某個建構元呼叫同一個class的另一個建構元


五.數字與靜態

1.static(靜態)的方法不能呼叫、使用非static的變數或方法

2.static的方法應該用class的名稱來呼叫

3.在java中的常數是把變數同時標示為static與final

4.常數的命名慣例是全部使用大寫字母

5.static是用來標示出不需class實體的method。一個static的method代表一種不依靠實體變數也就無需物件的行為

6.static變數是共用的

7.static變數會在該class的任何static的method執行之前就初始


六.例外處理

1.method可以抓住其他method所拋出的例外

2.例外總是會丟給呼叫方

3.在撰寫可能會拋出例外的方法時,它們都必須宣告成throws Exception

4.編譯器不會注意RuntimeException型別的例外,而是會關心checked exception的例外

5.方法可以拋出多個例外,但該方法的宣告要含有全部可能的checked exception(若有兩個或以上的例外有共同的父類別時,可以只宣告該父類別)

6.有多個catch區塊時,必須從小排到大

7.try與catch間不能有程式

8.method可以用throw關鍵字拋出例外物件:
throw new abcException();

9.finally區塊是用來放不管有沒有例外都得執行的程式


七.圖形使用者介面

1.取得按鈕的ActionEvent:1.實作ActionListener這個介面2.向按鈕登記(告訴它你要傾聽事件)3.定義事件處理的方法(實作介面上的方法)

2.GUI從建構視窗開始,通常會使用JFrame
JFrame frame = new JFrame();

3.JFrame與其他組件不同,不能直接加上組件,要用它的content pane

4.加入按鈕、文字欄位等物件:
frame.getContentPane().add(button);

5.要顯示視窗,必須指定尺寸與執行顯示動作
frame.setSize(300, 300);
frame.setVisible(true);

6.利用inner class 可實作同一個方法兩次。其建構的方式為:
class MyOuter{
    private int x;
    MyInner inner = new Myinner();
    public void abc() {inner.go();}

    class Myinner{ void go(){x = 1;}}
}

7.如果class想要知道按鈕的ActionEvent,你就得實作ActionListener這個interface

8.按鈕是ActionEvent的來源,因此它必須要知道有那些物件是需要事件通知的


八.使用swing

1.在swing中,所有的組件都是可以套疊的

2.pack()會使視窗的大小符合內含組件的大小

3.BorderLayout會把背景組件分割成五個區域。每個被管理的區域只能放上一個組件

4.BorderLayout可以把組件加到五個區域上
add(BorderLayout.EAST, panel);

5.FlowLayout中每個組件會依照理想大小呈現,並且會從左到右依照加入的順序來安置組件,若寬度超過時會自動換行

6.BoxLayout中每個組件會依照理想大小呈現,並且以垂直方向來安置組件

7.frame預設使用BorderLayout;panel預設使用FlowLayout

8.透過呼叫setLayout()可用來改變panel的layout manager


九.序列化與檔案輸出入

1.透過序列化可以儲存物件的狀態。序列化的物件保存了實體變數的值,因此之後可以在heap上帶回一模一樣的實體

2.使用ObjectOutputStream來序列化物件(java.io)

3.用FileOutputStream鏈結ObjectOutputStream來將物件序列化到檔案上

4.呼叫ObjectOutputStream的writeObject(theObject)來將物件序列化。不需叫用FileOutputStream的方法

5.物件必須implements Serializable這個介面才能被序列化

6.如果需要序列化程序能跳過某個實體變數,則把它標示為transient。transient變數在還原時會被賦予null或primitive的預設值

7.讀取物件的順序必須與寫入物件的順序相同

8.readObject()的回傳型別是Object,因此解序列化回來的物件還需要轉換成原來的型別

9.static變數不會被序列化,因為所有物件都是共用同一份static變數值。要記得static代表「每個class一個」,而不是「每個物件一個」。當物件被還原時,static變數會維持class中原本的樣子,而不是儲存時的樣子

10.以FileWriter來寫入文字檔案。將FileWriter鏈結到BufferedWriter可以提昇效率

11.以FileReader來讀取文字檔案。將FileReader鏈結到BufferedReader可以提昇效率

12.使用split()可以把String拆開,其中的分隔字元不會被當作資料來看待

13.如果某實體變數不能或不應被序列化,就把它標示為transient

14.有些變數不能被序列化的原因,可能是設計者忘記實作Serializable。,或者動探資料只可以在執行時求出而不能或不必儲存


十.網路與執行緒

1.用戶端與伺服器的應用程式透過Socket連線來溝通

2.TCP埠號是個16位元的值,用來指定特定的應用程式。它能夠讓用戶連結到伺服器上各種不同的應用程式

3.用戶端藉由建立Socket來連接伺服器
Socket s - new Socket("127.0.0.1", 4200);

4.一旦建立了連線,用戶端就可以從socket取得低階輸出入串流
sock.getInputStream();

5.建構BufferedReader鏈結InputStreamReader與來自Socket的輸入串流以讀取伺服器的文字資料

6.InputStreamReader是個轉換byte成字元的橋樑。它主要用來鏈結BufferedReader與低階的Socket輸入串流

7.建構直接鏈結Socket輸出串流的PrintWriter呼叫print()或println()來送出String給伺服器

8.伺服器可以使用ServerSocket來等待用戶對特定port的要求。

9.當ServerSocket接到要求時,它會做一個Socket連線來接受用戶端的要求

10.以小寫t敘述的thread是個獨立的執行緒

11.以大寫得T敘述的Thread是java.lang.Thread這個class。它的物件是用來表示執行緒

12.Thread需要任務,任務是實作過Runnable的實體

13.Runnable這個介面只有一個方法。run()會是新執行緒所執行的第一項方法

14.要把Runnable傳給Thread的建構元才能啟動新的thread

15.thread在初始化以後還沒呼叫start()之前處與新建構的狀態

16.呼叫Thread物件的start()後,會建構出新的執行空間,它處於可執行狀態,等待被挑出來執行

17.單處理器的機器只能有一個執行中的thread

18.Thread.sleep()這個static的方法可以強制thread進入等待狀態直到設定時間為止
Thread.sleep(200)//睡眠200毫秒

19.sleep可能會拋出InterruptedException例外,所以要包在try/catch區塊,或把例外也宣告出來

20.可以用setName()來幫thread命名,通常是用來除錯

21.如果兩個或以上的thread存取相同的物件,可能會引發資料損毀

22.要讓物件在thread上有足夠的安全性,就要判斷出哪些指令不能被分割執行

23.使用synchronized關鍵字修飾方法,可以防止兩個thread同時進入同一物件的同一方法

24.一旦某個thread進入該物件的同步化方法,其他thread就無法進入該物件上的任何同步化thread


十一.集合與泛型

1.TreeSet集合:以有序狀態保持並可防止重複

2.HashMap集合:可用成對的name/value來保存與取出

3.LinkedList集合:針對經常插入或刪除中間元素所設計的高效率集合(除非元素量很大,否則實際還是ArrayList較為實用)

4.HashSet集合:防止重複的集合,可快速地找尋相符的元素

5.LinkedHashMap集合:類似HashMap,但可記住元素插入的順序,也可以設定成依照元素上次存取的先後來排序

6.排序可以使用TreeSet或Collections.sort()。TreeSet在每當插入新項目時,都必須花時間找出適當位置;而ArrayList只需把項目放在最後面即可

7.泛型的主要目的是讓你能寫出有型別安全性的集合,讓問題可能在編譯期就能抓到

8.叫用單一參數的sort(List o)代表由list元素上的compareTo()來決定順序。因此元素必須實作Comparable這個介面

9.叫用sort(List o, Comparator c)代表不會叫用list元素的compareTo(),而會使用Comparator的compare()。代表list元素不需要實作Comparable

10.Collection的三個介面:
(1).LIST:知道某物在系列集合中的位置。可以有多個元素參考相同的物件
(2).SET:不容許重複的集合(被認為相等的兩個物件也不行)
(3).MAP:使用成對的鍵值與資料值。兩個key可以參考相同的物件,但key不能重複
(4).參考相等性:參考到heap上同一物件的兩個參考是相等的
(5).物件相等性:heap上的兩個不同物件在意義上相同的
(6).若hashcode是相異的,則HashSet會假設物件不可能是相同的,因此必須改寫過hashCode()來確保物件有相同的值
(7).要使用TreeSet,下列其中一項必為真:1.集合中的元素必須是有實作Comparable的型別2.使用改寫過、取用Comparator參數的建構元來建構TreeSet
(8).在方法的參數中使用萬用字元<?>時,你只能叫用元素中的方法,但不能新增元素


十二.package,jar與程式部署

1.要讓編譯過的class可以放在正確的package目錄中,使用-d編譯旗標:
%javac -d ../xxx/abc.java

2.以下面的命令格式來建構jar檔案
jar -cvfm xx.txt abc.jar xxxx

3.以下面的命令格式來執行jar檔案
java -jar abc.jar

4. .jlnp檔案是用來描述JWS應用程式的XML文件。它有tag以指定JAR的名稱與位置,以及帶有main()的class名稱

5.當瀏覽器從伺服器上取得 .jlnp檔案時,瀏覽器就會啟動JWS的helper app

6.JWS的helper會讀取 .jlnp來判斷要從伺服器上下載的可執行JAR

7.取得JAR之後它就會叫用 .jlnp指定的main()


十三.遠端部署的RMI

1.在某heap上的物件無法拿到不同heap上的物件參照

2.stub是個處理低階網路細節的輔助性物件,它會把方法的呼叫包裝起來送到伺服氣上

3.當用戶端呼叫遠端的方法時,其實是呼叫stub上的方法

4.啟動remote介面來建構遠端服務

5.remote介面必須繼承過java.rmi.Remote這個介面,且所有的方法都必須宣告RemoteException

6.遠端服務應該要繼承過UnicastRemoteObject

7.遠端服務必須要有宣告RemoteException的建構元(因為父類別的建構元有宣告)

8.遠端服務的物件必須要向RMI registry登記

9.使用靜態的Naming.rebind()來登記遠端服務

10.RMI registry必須在同一台機器上與遠端服務一起執行,且須在物件的登記之前啟動

11.用戶端會以Naming.lookuup()查詢遠端服務

12.一般的servlet是繼承過HttpServlet並改寫過doGet()與doPost()來建構的

13.servlet可以透過doGet()的參數取得輸出串流來組成回應的網頁



※補充:


1.條件運算符號 ?: 用法:
int score = 10
String s1 = x
String s2 = y
String c = score >= 5 ? s1 : s2
s.o.p(c)
結果為x

說明:條件式若為true,則取「?」後之值;反之若為false,則取「:」後之值


2.標籤Label用法:
labA: //1.標籤與迴圈間不得插入其他程式碼 2.須以「:」結尾
for(...){...
  if(..){...
    for(...){...
      if(...){
        break labA
      }
    }
  }
} //break至此


3.for-each用法:
int [] x = {1,2,3}
for(int y : x)
s.o.p(y)
結果為1 2 3

說明:依序取出x陣列之值並放至y


4.陣列排序與搜尋:
需先import java.util.Arrays
Arrays.sort(x) //升冪排序
Arrays.binarySearch(x, 10) //搜尋。搜尋前須先排序。傳出的值為索引值。若無欲搜尋之值,則回傳該值在此陣列內排序位置的負索引值再-1


5.陣列傳址:
int [] x = {1}
int [] y = x //此為將x內所儲存的記憶體位址複製一份給y。一旦x改變,y亦改變;反之亦然


6.陣列傳值:
int [] x = {1}
int [] y = Arrays.copyOf(x, x.length) //可指定長度,若大於陣列之長度,則超過的部分會存放0

沒有留言:

張貼留言