head first java讀書筆記

Solon Tan發表於2017-02-19

head first java讀書筆記

1. 基本資訊

  • 頁數:689
  • 閱讀起止日期:20170104-20170215

2. 標籤

  • Java入門

3. 價值

  • 8分

4. 主題

使用物件導向的思路介紹Java的基礎知識,從物件的基本概念、變數、方法,到函式庫,整合與多型,靜態,再到GUI,序列化,網路,資料結構,最後介紹釋出和遠端呼叫。

5. 綱要

  1. Java的基本介紹-第1章
  2. 物件的基本介紹(變數與方法)-第2-5章
  3. 函式庫-第6章
  4. 物件的深入-繼承、多型、建構函式-第7-9章
  5. 靜態的變數或方法-第10章
  6. 異常處理-第11章
  7. GUI-第12-13章
  8. 序列化與IO-第14章
  9. 網路與執行緒-第15章
  10. 常用資料結構-第16章
  11. 包與釋出程式-第17章
  12. 遠端過程呼叫、servlets等-第18章
  13. 附錄

6. 點評

本書最大的啟發是建立物件導向的基本思想,萬物皆在物件中,到底是如何組成和實現的。

7. 摘錄

7.1 Java的基本介紹

  1. Java程式包括:原始碼、編譯器、輸出(class檔案)、JVM;
  2. 最常用的java

     public class ClassName {
         public static void main(String[] args){
             System.out.println("Hello World!");
         }
     }
  3. Java不能像C一樣使用整型做測試條件
  4. (int)(Math.random()*length)來出現隨機數;

7.2 物件的基本介紹

  1. 物件本身已知的事物被稱為例項變數,物件可以執行的動作被稱為方法;
  2. 類是物件的藍圖;
  3. main的兩種用途:測試真正的類,啟動你的java應用程式;
  4. Java的程式在執行期是一組會互相交談的物件;
  5. 變數有兩種型別primitive主資料型別和引用;
  6. primitive主資料型別:boolean, char(0~65535), byte(-128~127), short(-32768~32767), int, long, float, double。
  7. 沒有物件變數,只有引用到物件的變數;引用變數更像是物件的遙控器;
  8. 沒有引用到任何物件的引用變數的值為null;
  9. 如果堆上的物件沒有任何引用變數,便會被回收;
  10. 陣列就像杯架,陣列變數就是陣列物件的遙控器;
  11. 將例項變數標記為private,將getter和setter標記為public;
  12. 例項變數永遠都會有預設值,引用變數的預設值是null;區域性變數沒有預設值。
  13. 程式設計的方法:找出類應該做的事情,列出例項變數和方法,編寫偽碼,編寫測試用的程式,實現類,測試方法,排錯或重新設計。
  14. 偽碼描述要做什麼事情,而不是如何做。
  15. Interger.parseInt()只會在所給的String為數字時有用。

7.3 API

  1. ArrayList listName = new ArrayList();
  2. Java的API中,類是包含在包中的。使用時,必須import 類全名或直接打出去全名。除非是來自於java.lang這個包中,比如System, String, Math等。

7.4 物件深入

  1. extends表示繼承,繼承搜尋方法時,會從底層向祖先搜尋;
  2. 繼承是是一個,例項變數是有一個;
  3. public會被繼承,private不會被繼承。
  4. IS-A是單方向的;
  5. 繼承的意義有二:避免了重複的程式碼;定義出共同的協議;
  6. 多型為宣告父類的物件引用指向子類的物件;
  7. 通過多型,可以寫出即使引進新型子類時,也不必修改的程式;
  8. 繼承雖然沒有層次的限制,但一般不會超過2層;
  9. 標識出final的類可以確保方法都是自己需要的版本,final也可以防止特定的方法被覆蓋,只要加在方法前;
  10. 覆蓋父類方法需要滿足兩個條件:引數必須要一樣,且返回型別要相容;不能降低方法的存取許可權;
  11. abstract表示抽象,抽象類不會被初始化;
  12. abstract可以放在方法前,直接以分號結尾。抽象方法只能放在抽象類中,所有的抽象方法在子類中必須被實現;
  13. Java中,所有的類都繼承自object。object有equals,getClass,hashCode,toString等方法。
  14. 介面是為了解決多重繼承的問題出現的,它沒有例項變數。像是一個100%的純抽象類,使用interface定義,所有的方法都是抽象的。其他類用implements來實現介面的方法。類是可以實現多個藉口的。
  15. 如果新的類無法對其他類通過IS-A測試,就設計不繼承的類;
  16. 只有在需要某類的特殊化版本時,已覆蓋或增加新的方法來繼承現有的類;
  17. 當你需要定義一群子類的模板,又不想初始化此模板時,使用抽象類;
  18. 如果定義出類可以扮演的角色,使用介面;
  19. 使用super關鍵字執行父類的方法;
  20. 抽象類可以帶有抽象和非抽象的方法;
  21. 方法呼叫和區域性變數在棧空間,所有的物件在堆空間;
  22. 建構函式沒有型別,也不會被繼承。通常一定要有沒有引數的建構函式。如果有了一個有引數的建構函式,則沒引數的建構函式必須自己寫才會有,否則建立會出錯。
  23. 通常狀況下,類的建構函式是public。
  24. 建構函式的呼叫鏈是自頂向下的,即先執行父類,再執行子類。
  25. 子類的建構函式如果想呼叫父類,使用super();通常狀況下,super會被編譯器預設呼叫沒有引數的版本,顯示呼叫的話,必須要把super();放到第一行。
  26. 可以使用this(args)呼叫過載版的其他的建構函式,例如無引數的建構函式,加個預設值呼叫有引數的建構函式。this(Color.Red)

7.5 靜態的變數或方法

  1. 靜態方法不需要建立例項變數就可以呼叫,像Math.abs(-1);
  2. 如果類只有靜態方法,即要限制非抽象類初始化,可以將建構函式設定為private;
  3. 靜態方法不能呼叫非靜態的變數或方法,例如在main中呼叫;但可以呼叫靜態變數或方法。
  4. 類中靜態變數的值,對所有例項都相同,均是共享的;即例項變數每個例項一個,靜態變數每個類一個。
  5. public static final double PI=3.1415public表示可供各方讀取,static表示不用建立例項即可使用,final表示不變;靜態final變數預設取名大寫,且必須初始化。
  6. final的變數代表不能改變,final的方法不能被覆蓋,final的類不能被繼承;
  7. 使用類似ArrayList時,要用到對主型別資料的封裝。因為ArrayList設計成只接受類和物件。Java5.0之前,int不能直接加入ArrayList,5.0之後可以了,因為加入了autoboxing。Integer iWarp = new Integer(i); int unWrapped = iWrap.intValue();利用上述解包裝;
  8. 主資料型別的靜態方法:Integer.parseInt("2"), new Boolean("true").booleanValue();Double.toString(d);
  9. 格式化輸出String.format("%,d",1000);
  10. 日期的格式化輸出:%tc 完整的日期和時間,%tr是時間,%tA %tB %td 分別是星期,月份和日期。如果不想重複輸入引數,可以使用String.format("%tA, %<tB %<td", today);
  11. java.util.Calendar物件來操作日期

    Calendar cal = Calendar.getInstance();
    cal.set(2017,1,6,15,40);
    cal.getTimeInMillis();
    cal.HOUR_OF_DAY
    cal.add(cal.DATE, 30);//月份滾動
    cal.roll(cal.DATE, 30);//月份不動
    cal.set(cal.DATE, 1);
    //重要的方法
    add(int field, int amount)
    get(int field)
    getInstance()
    getTimeInMillis()
    roll(int field, int amount)
    set(int field, int amount)
    set(year,month,day,hour,minute)
    setTimeInMillis(long millis)
    //關鍵欄位
    DATE / DAY_OF_MONTH
    HOUR / HOUR_OF_DAY
    MILLISECOND
    MINUTE
    MONTH
    YEAR
    ZONE_OFFSET
  12. import static java.lang.System.out;靜態的import可以到方法,然後直接呼叫out即可,不建議使用;

7.6 異常處理

  1. Java通過throws語句來告訴你所有的異常行為;把有風險的程式放在try塊中,用catch塊擺放異常的處理程式;異常時Exception型別的物件;
  2. 會丟擲異常的方法必須要宣告它有可能會這麼做。方法可以抓住其他異常,異常總會丟回給呼叫方;

     public void takeRisk() throws BadException{
         if (abandonAllHope){
             throw new BadException();
         }
     }
     public void crossFingers(){
         try{
             anObject.takeRisk();
         }catch (BadException ex){
             System.out.println("Aaargh");
             ex.printStackTrace();
         }
     }
  3. try/catch塊用來處理真正的異常,而不是程式的邏輯錯誤。
  4. 開發與測試期間發生RuntimeException是不會受編譯器關於是否宣告它會丟擲RuntimeException的檢查的,也不會管呼叫方是否認識到該異常;
  5. 無論成功或者失敗都要執行的放在finally中;即使try和catch都有return也一樣。
  6. throws可以丟擲多個異常。throws Exception1, Exception2;catch也可以用類似switch語句一樣來分別處理,但是要從小到大;
  7. 異常也可以是多型的,可以用所丟擲的異常父型來catch異常。即可以用Exception ex來catch異常,但是不推薦這麼做;
  8. duck異常表示,當呼叫有異常的方法,也宣告會丟擲異常時,可以不把此方法的呼叫放在try/catch塊中,但是不推薦這麼做。

7.7 GUI相關

  1. GUI的流程是建立frame,建立widget,加在widget,顯示出來。
  2. 監聽和事件源之間的溝通通過程式程式碼呼叫button.addActionListener(this)來向按鈕註冊。按鈕會在事件發生時,呼叫註冊該介面的方法actionPerformed(theEvent)

     import javax.swing.*;
     import java.awt.event.*;
    
     public class SimpleGui1B implements ActionListener{
         JButton button;
    
         public static void main(String[] args){
             SimpleGui1B gui = new SimpleGui1B();
             gui.go();
         }
         public void go(){
             JFrame frame = new JFrame();
             button = new JButton("click me");
    
             button.addAcitonListener(this);
    
             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
             frame.getContentPane().add(button);
    
             frame.setSize(300,300);
             frame.setVisible(true);
         }
    
         public void actionPerformed(ActionEvent event){
             button.setText("I've been clicked!");
         }
     }
  3. frame預設有東西南北中五個位置來放置widget;
  4. 當有多個widget需要監聽事件時,用內部類來解決;

     public void go(){
         //...
         labelButton.addActionListener(new LaberlListener());
         colorButton.addActionListener(new ColorListener());
         label = new JLabel("I'm a label")
         //...
     }
     class LaberListener implements ActionListener {
         public void actionPerformed(ActionEvent event){
             labnel.setText("Ouch!")
         }
     }
  5. 不同的事件有不同的對應回撥函式,ActionListener對應的回撥函式是actionPerformed,通過addActionListener新增。
  6. 每個背景元件都可以有自定義規則的佈局管理器。BorderLayout表示五個區域,是frame預設的,FlowLayout表示從左至右,有必要時換行,是panel預設的;BoxLayout以垂直排列;

     panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
     panel.add(button);
     frame.getContentPane().add(BorderLayout.North, panel);
  7. JTextField文字框元件,JTextArea可滾動的文字框元件,JCheckBox元件,JList元件均為常用元件。

7.8 序列化與IO

  1. 儲存物件的狀態可以有兩種辦法,序列化(自己的Java程式讀),純文字檔案(公共格式,其他程式可讀)。
  2. 序列化寫入的步驟:建立FileOutputStream對應一個檔案xxx.ser,有FileStream建立ObjectOutputStream,由ObjectOutputStream寫入object,關閉ObjectOutputStream。其中需要注意,能夠寫入ObjectOutputStream的object必須implements Serializable,但是不需要實現任何方法。

     FileOutputStream fileStream = new FileOutputStream("MyGame.ser");
     ObjectOutputStream os = new ObjectOutputStream(fileStream);
     os.writeObject(characterOne);
     os.close();
  3. 當一個類可以序列化時,必須所有的例項變數都能被序列化,如果某個變數不需要序列化,需要標記transient,例如transient String currentID;
  4. 解序列化步驟,建立FileInputStream讀取一個檔案,建立ObjectInputStream,讀取物件,轉換物件型別,關閉。

     FileInputStream fileStream = new FileInputStream("MyGame.ser");
     ObjectInputStream os = new ObjectInputStream(fileStream);
     Object one = os.readObject();
     GameCharacter elf = (GameCharacter) one;
     os.close()
  5. 讀寫文字檔案。注意可以使用緩衝區的方法來減少磁碟IO。使用writer.flush()強制緩衝區內容寫入磁碟。

     import java.io.*;
     class WriteAFile{
         public static void main(String[] args){
             try {
                 FileWriter writer = new FileWriter("Foo.txt");
                 writer.write("hello, foo!");
                 //BufferedWriter bWriter = new BufferedWriter(writer);
                 //bWriter.flush();
                 writer.close();
                 File myFile = new File("Foo.txt");
                 FileReader fileReader = new FileReader(myFile);
    
                 BufferedReader reader = new BufferedReader(fileReader);
                 String line = null;
                 while((line = reader.readLine()) != null){
                     System.out.println(line);
                 }
                 reader.close();
             } catch(IOException ex){
                 ex.printStackTrace();
             }
         }
     }
  6. java.io.File類的操作

     //建立出File物件
     File f = new File("MyCode.txt");
     //建目錄
     File dir = new File("Chapter_8");
     dir.mkdir()
     //列出目錄內容
     if (dir.isDirectory()){
         String[] dirContents = dit.list();
     }
     //取得絕對路徑
     dit.getAbsolutePath();
     //刪除檔案
     boolean isDeleted = f.delete()
  7. 每個物件被序列化的同時,都會帶上一個類的版本的識別ID,即serialVersionUID。因此要注意版本。

7.9 網路與執行緒

  1. 網路接收訊息的步驟:建立socket連線,輸入到底層的InputStreamReader上,轉換到緩衝區字元BufferedReader,讀取資料;

     Socket chatSocket = new Socket("127.0.0.1", 5000);
     InputStreamReader stream = new InputStreamReader(chatSocket.getInputStream());
     BufferedReader reader = new BufferedReader(stream);
     String message = reader.readline();
     reader.close();
  2. 寫訊息的流程是:建立socket,getOutputSream並建立PrintWriter,寫入資料;

     Socket chatSocket = new Socket("127.0.0.1", 5000);
     PrintWriter writer = new PringWriter(chatSocket.getOutputStream());
     writer.println("haha");
     writer.close();
  3. 伺服器端建立服務的流程為:建立ServerSocket,等待客戶端連線,客戶連線後,呼叫accept方法建立新的socket。

     ServerSocket serverSock = new ServerSocket(5000);
     while(true){
         Socket sock = serverSock.accept();
         PrintWriter writer = new PrintWriter(sock.getOutputStream());
         writer.println("haha");
         writer.close();
     }
  4. Thread類用於建立執行緒,它有void join();void start();static void sleep();等方法。
  5. 啟動新執行緒的流程是:建立Runnable物件,建立Thread物件,並賦值Runnable任務;啟動Thread。
  6. Runnable是一個介面,它只有一個方法public void run()。它就是執行緒要執行的工作。

     public class MyRunnable implements Runnable {
         public void run(){
             go();
         }
         public void go(){
             System.out.println("top o' the stack");
         }
     }
    
     class ThreadTestDrive{
         public static void main(String[] args){
             Runnable threadJob = new MyRunnable();
             Thread myThread = new Thread(threadJob);
             myThread.start();
             System.out.println("back in main");
         }
     }
  7. 新建執行緒執行緒有新建(new),可執行(start),執行中,三個狀態,可執行和執行中兩個狀態是來回切換的,由JVM排程決定,是隨機不可控的。最多隻能靠sleep來影響最小保證時間。
  8. 執行緒不可重複啟動。
  9. 執行緒的名字可以通過myThread.setName("Solon's Thread")來設定,並可通過呼叫Thread.currentThread().getName()來獲取。
  10. 執行緒會產生併發性問題(concurrency),併發性問題會引發競爭狀態(race condition),競爭狀態會引發資料損毀。舉個例子,兩個執行緒共用一個餘額,每次用錢時,先檢查餘額,再扣錢。這樣會由於競爭原因出現負數。所以需要一把鎖,來保證一個方法一次只能被一個執行緒呼叫,即用synchronized關鍵字。

    private synchronized void makeWithDrawa(int amount){
        //...
    }
  11. 要注意鎖是鎖在物件上的,只有物件包含同步化方法時才起作用。物件就算有多個同步化方法,也還是隻有一個鎖。
  12. 同步化可以只修飾幾行,這樣可以減小原子操作的範圍,提高效率。

    private void makeWithDrawa(int amount){
        //...
        synchronized(this){
            //...
        }
    }
  13. 兩個執行緒和兩個物件就可以引起死鎖,各自佔有一個資源,又需要呼叫彼此的資源。
  14. 靜態的方法是執行在類上的,當要對靜態的方法做同步化是,會使用類本身的鎖。

7.10 常用資料結構與泛型

  1. TreeSet一有序狀態保持並可防止重複;
  2. HashMap-KV來儲存;
  3. LinkedList-針對經常插入和刪除的集合;沒有ArrayList常用;
  4. HashSet-防重複的集合,快速查詢;
  5. LinkedHashMap-類似HashMap,但可記住元素的插入順序,可按照存取順序來排序;
  6. 可用java.util下的Collections.sort(List list)來給ArrayList排序,此函式會直接改變list的順序。
  7. 不用泛型時,任何object物件都可以加入ArrayList,造成混亂。使用泛型,只有任一單一型別可加入;
  8. 泛型有三件事是重要的:

     new ArrayList<Song>(); //建立例項
     ArrayList<Song> songList = new ArrayList<song>(); //宣告指定泛型型別的變數
     void foo(ArrayList<Song> list); //宣告或呼叫指定泛型的方法
  9. 在說明檔案中,一般用E表示指定型別;

     public class ArrayList<E> extends AbstractList<E> implements List<E> ...{
         public boolean add(E o)
     }
  10. 運用泛型的方法可以使用未定義在類宣告的型別引數。

    public <T extends Animal> void takeThing(ArrayList<T> list)
    //與後續的萬用字元相同
    public void takeThing(ArrayList<? extends Animal>)
    //與下面不一樣,下面的只能使用Animal,不能使用其子類
    public void takeThing(ArrayList<Animal> list) 
  11. 以泛型的觀點來說extends可以代表extend或implement,表示是一個。
  12. 如果要對自定義類實現排序,有兩種方法,一是實現該類的Comparable介面,這個介面有compareTo方法。可以呼叫已有的型別來輔助實現該方法;二是增加Comparator類的引數來比較。
  13. 可以呼叫HashSet的addAll方法,來生成ArrayList對應的佇列;
  14. 同樣如果要使用HashSet去除重複,針對自定義類,要覆蓋equals方法和hashCode方法。它的比較過程是先比較hashCode(),如果相同,再比較equals。

    class Song implements Comparable<Song>{
        ...
        public boolean equals(Object aSong){
            Song s = (Song)aSong;
            return getTitle().equals(s.getTitle());
        }
        public int hashCode(){
            return title.hashCode();
        }
    }
  15. HashMap適合用KV場景儲存資料

    HashMap<String, Integer> scores = new HashMap<String, Integer>();
    scores.put("Bert", 43);
    System.out.println(scores.get("Bert"));
  16. 泛型引數和陣列引數的區別

    public void takeAnimals1(ArrayList<Animal> animals)
    public void takeAnimals2(Animal[] animals)
    //takeAnimals1(new ArrayList<Dog> dogs)會出錯,編譯錯誤
    //takeAnimals2(new Dog[] dogs)不會出錯
    //前者可以防止在函式中進行Dog的特有相關操作,後者在執行期如果執行相關操作,會丟擲異常
  17. 為了解決上述前者的問題,可以使用萬用字元

    public void takeAnimals3(ArrayList<? extends Animal> animals)
    //為了防止此時,將ArrayList<Dog>中加入Cat,當用萬用字元時,不能對佇列做加入操作

7.11 包與釋出程式

  1. 可以使用-d class_path來將原始碼與類檔案相分離,實現對原始碼的保護;

     javac -d ../classes *.java
  2. jar類似tar命令,它有自己的規則。首先要確定所有的類檔案都在classes目錄下,其次要有manifest.txt檔案來描述哪個類帶有main()方法,最後執行命令打jar包

     cat manifest.txt
     Main-Class:MyApp
     cd MiniProject/classes
     jar -cvmf manifest.txt app1.jar *.class
  3. 如果jar包指定了manifest,則可以執行java -jar app1.jar
  4. 除非類是包的一部分,否則Java虛擬機器不會深入其他目錄去找。
  5. 用包防止類名衝突,可以把類放到各個包裡。就像java.util.ArrayList。
  6. 而為了防止包命名衝突,一般反向使用domain作為包名稱。

     com.headfirstbooks.Book
     com.headfirstjava.projects.Chart
  7. 選定包名稱後,需要再類的原始碼的第一行將類加入包中package com.headfirstjava;。然後要設定對應的目錄結構。
  8. 一般Java程式的路徑為專案根目錄下有source和classes兩個檔案,source目錄下為包路徑和原始碼,這樣用-d ../classes編譯後,-d會在classes目錄下建立對應的目錄和class檔案。
  9. 按照上述約定時,manifest檔案也放在class目錄下,一般為Main-Class:com.headfirstjava.PackageExcise
  10. 在classes目錄下執行jar語句打包,這裡只要指定com路徑就行。

     jar -cvmf manifest.txt packEx.jar com
  11. 使用jar -xf packEx.jar解壓後會發現有META-INF目錄,其下有MANIFEST.MF檔案,即為寫入的對應檔案。
  12. JWS即Java Web Start,使用者能通過網頁上的某個連線來啟動Java程式,一旦程式下載後,下次就能獨立於瀏覽器來執行,它是通過網路來發布程式的一種手段。jnlp檔案是個描述應用程式可執行JAR檔案的XML檔案。
  13. 製作可執行jar程式;編寫jnlp檔案;兩者均放入Web伺服器;Web伺服器設定新型別application/x-java-jnlp-file;設定網頁連結到jnlp檔案<a href="MyApp.jnlp">Launch My App</a>

7.12 遠端過程呼叫、servlets等

  1. 遠端過程呼叫最早是為了利用Server端的強大處理能力。RMI全稱Remote Method Invocation;
  2. RMI需要伺服器與伺服器helper和客戶端與客戶端helper。helper假裝成服務,但其實只是真實服務的代理;
  3. 使用RMI時要確定協議,兩端都是Java可使用JRMP協議,IIOP可以呼叫Java物件或其他型別的遠端方法。
  4. 在RMI中客戶端的helper稱為stub,客戶端的helper成為skeleton
  5. 建立遠端服務的流程是建立介面(extends Remote),實現類(extends UnicastRemoteObject impements MyRemote),rmic產生stub與skeleton(rmic MyRemoteImpl),啟動RMI registry(rmiregistry),啟動遠端服務(Naming.rebind("Remote Hello", serviceMyRemote))。
  6. 客戶端查詢RMIregistry((MyRemote)Naming.lookup("rmi://127.0.0.1/Remote Hello")),RMIregistry返回stub物件,客戶端呼叫stub上的方法;
  7. 注意點:啟動遠端服務前啟動registry;引數和返回型別可序列化;
  8. servlet相當於Java的CGI,可以處理使用者提交的請求,並將結果返回給瀏覽器的網頁;
  9. 建立並執行serverlet的步驟:找到網頁伺服器可以存放servlet的地方;取得servlet.jar並新增到classpath上(其不是標準函式庫的一部分);extends HttpServlet來編寫servlet的類;編寫html來呼叫servlet;給伺服器配置html和servlet;
  10. servlet一般通過覆蓋HttpServlet的doGet和doPost來建立;它輸出帶有完整標識的HTML網頁;
  11. EJB是Enterprise JavaBeans,它具有一組光靠RMI不會有的服務,比如交易管理、安全性、併發性、資料庫和網路功能等;EJB伺服器作用於RMI呼叫和服務層之間。service helper呼叫EJB object,object呼叫Enterprise bean,後者再呼叫DB等操作;
  12. Jini也使用RMI,但具有自適應探索(接收服務註冊和客戶端呼叫查詢)和自恢復網路(用心跳檢查服務)的功能;

    7.13 附錄

  13. 按位非~,按位與&,按位或|,按位異或^;
  14. 右移>>,無符號右移>>>;
  15. String具有不變性,放在String pool中,不受Garbage Collector管理。
  16. 包裝類沒有setter,其具有不變性。例如new Integer(42),永遠都是42。
  17. 斷言可以用來測試,它比println的好處是沒有特別設定的話,它會自動被JVM忽略,也可專門開啟斷言除錯程式。

     assert (height > 0) : "height = " + height + " weight = " + weight;
     //冒號後面的語句可以是任何返回非null值得語句,但一定要注意不要在這裡改變物件的狀態
     //斷言的編譯和普通編譯沒差別,執行時有差異。
     javac TestDriveGame.java
     java -ea TestDriveGame
  18. new Foo().go()是一個呼叫go方法,但又不需要維持對Foo引用的方式;
  19. 靜態巢狀類,和普通類很像,可通過new Outer.Inner()來建立。可存取外層靜態私有變數;
  20. 非靜態的巢狀類,通常被稱為內部類。
  21. 匿名內部類。

     //button.addActionListener(quitListener); //通常是傳遞一個內部類的例項
     //雖然ActionListener是個介面,而且我們不能宣告一個介面的例項,但匿名內部類是個例外
     button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ev){
             System.exit(0);
         }
     });
  22. public任何程式程式碼都可公開存取;default只在統一包中的預設事物能夠存取;protected可允許不在同一包的子類,繼承該部分;
  23. 對於常用的可變String,一般使用StringBuilder,Thread安全環境中,採用StringBuffer;
  24. 二維陣列是指陣列的陣列,new int [4][2]其實是建立一個包含四個元素的陣列,每個元素是一個長度為2的陣列。
  25. 列舉相對於普通常量的優勢是限定了範圍,其實際是繼承了java.lang.Enum。宣告時使用public enum Members {JERRY, BOBBY, PHIL};
  26. 每個列舉都內建values()可以用於遍歷操作;
  27. 可以在enum中加入建構函式,方法、變數和特定常量的內容;

8. 相關

暫無

相關文章