【學習筆記】《Java編程思想》 第8~11章

第八章 多態

  1. 多態的條件:

    1. 要有繼承html

    2.父類對象引用子類對象java

    3. 要有方法的重寫數組

  2. 多態的做用:消除類型之間的耦合關係。
  3. 將一個方法調用與一個方法主體關聯起來稱做綁定。若在程序執行前進行綁定,叫作前期綁定;在運行時根據對象的類型進行綁定,叫作後期綁定,也叫動態綁定、運行時綁定。
  4. Java中除了static方法和final方法以外,其餘全部的方法都是後期綁定。因此final的做用還有關閉動態綁定。
  5. 只有非private方法才能夠被覆蓋,可是還須要密切注意覆蓋private方法的現象,這時雖然編譯器不會報錯,可是也不會按照咱們的預期的執行。
  6. 若是某個子對象要依賴於其餘對象,銷燬的順序應該和初始化順序相反。
  7. 域是不具備多態性的,只有普通的方法調用是多態的。若是直接訪問某個域,這個訪問就將在編譯期進行解析,即域是靜態解析的。靜態方法也是不具備多態性的

第九章 接口

  1. 抽象方法和抽象類:

    抽象方法是不完整的,僅有聲明而沒有方法體
    abstract void f();

    包含抽象方法的類叫作抽象類;若是一個類包含一個或多個抽象方法,該類必須被定義爲抽象的
    若是從一個抽象類繼承,並想建立該類的對象,那麼就必須爲基類中的全部抽象方法提供方法定義;若是不這樣作,那麼導出類也是抽象類,且編譯器會強制咱們用abstract關鍵字來限制這個類。
  2. interface這個關鍵字產生一個徹底抽象的類,它根本就沒有提供任何具體實現安全

    要讓一個類遵循某個特定接口(或一組接口),須要使用implements關鍵字多線程

  3. 若是從一個非接口的類繼承,那麼只能從一個類繼承;能夠繼承多個接口
  4. 接口能夠多繼承接口來擴展,接口還能夠嵌套。
  5. 接口是實現多重繼承的途徑,而生成遵循某個接口的對象的典型方式就是工廠方法。在工廠對象上調用的是建立方法,而該工廠對象將生成接口的某個實現的對象。
  6. 接口能夠包含域,且隱式地是static 和 final的。
  7. 接口關鍵字interface前能夠添加public修飾符,不加默認是包訪問權限,接口的方法默認都是public的。

第十章 內部類

  1. 將一個類的定義放在另外一個類的定義內部,這就是內部類。
  2. 從外部類的非靜態方法以外的任意位置建立某個內部類的對象,那麼必須具體地指明這個對象的類型OuterClassName.InnerClassName。
  3. 非static的普通內部類自動擁有對其外圍類全部成員的訪問權(包括private)

  4. 若是須要生成對外部類對象的引用,可使用外部類的名字後面緊跟.this
    public class DotThis {
        void f() {
    	System.out.println("DotThis.f()");
        }
        public class Inner {
    	public DotThis outer() {
    	    return DotThis.this;//經過.this返回外部類對象
    	}
        }
        public Inner inner() {return new Inner();}
        public static void main(String[] args) {
    	DotThis dotThis = new DotThis();
    	DotThis.Inner dtInner = dotThis.inner();
    	dtInner.outer().f();
        }
    }
    

    若是要建立內部類對象,必須使用外部類對象和.new框架

    public class DotNew {
        public class Inner {}
        public static void main(String[] args) {
            DotNew dn = new DotNew();
            DotNew.Inner dni = dn.new Inner();
        }
    }
    
  5. 若是擁有的是抽象類或者具體類,而不是接口,那麼就只能使用內部類實現多重繼承
    public class Example1 {
        public String getName() {
            return "llb";
        }
    }
    public class Example2 {
        public int getAge() {
            return 25;
        }
    }
    
    public class MultiImplementation {
        private class test1 extends Example1 {
            public String getName() {
                return super.getName();
            }
        }
        private class test2 extends Example2 {
            public int getAge() {
                return super.getAge();
            }
        }
        public String getName() {
            return new test1.getName();
        }
        public int getAge() {
            return new test2.getAge();
        }
    
        public static void main(String[] args) {
            MultiImplementation my = new MultiImplementation();
            System.out.println("姓名: " + my.getName());
            System.out.println("年齡: " + my.getAge());
        }
    }
    
  6. 局部內部類是指內部類定義在方法或做用於內ide

      • 局部內部類不能有訪問說明符
      • 局部內部類能夠訪問當前代碼塊內的常量以及此外圍類的全部成員

     局部內部類會跟着其餘類一塊兒經過編譯,可是在定義該局部內部類的方法或做用域以外,該局部內部類是不可用的函數

  7. 內部類聲明爲static時,再也不包含外圍對象的引用.this,稱爲嵌套類(與C++嵌套類大體類似,只不過在C++中那些類不能訪問私有成員,而在Java中能夠訪問)。
    - 建立嵌套類,不須要外圍對象。
    - 不能從嵌套類的對象中訪問非靜態的外圍對象。
    public class OuterClass {
        private static String address = "Shanghai";
        public static class StaticInnerClass {
            public String getAddress() {
    	    return address;
    	}
        }
        public static void main(String[] args) {
    	OuterClass.StaticInnerClass sic = new  
                                         OuterClass.StaticInnerClass();
    	String address = sic.getAddress();
    	System.out.println(address);
        }
    }
    
  8. 匿名內部類建立方式爲:工具

    new 外部類構造器(參數列表)或接口 {}
    1. 在定義類的同時就生成了該內部類的一個實例,隨後該類的定義會消失,因此匿名內部類不能被重複使用
    2. 匿名內部類必須繼承一個父類或者實現一個接口,可是也只能繼承一個父類或實現一個接口
    3. 匿名內部類中不能定義構造方法(沒有類名),不能存在任何的靜態成員變量和靜態方法
    4. 匿名內部類不能是抽象的,它必須實現所繼承的類或者實現的接口中的所有抽象方法
    public interface Contents {
        int value();
    }
    public class Parcel7 {
        public Contents contents() {
            return new Contents() {
                private int i = 1;
                public int value() { return i; }
            };
        }
    
        //等價於
    /*
        class MyContents implements Contents {
            private int i = 1;
            public int value() { return i; }
        }
        public Contents contents() { return new MyContents(); }
    */
    
        public static void main(String[] args) {
            Parcel7 parcel7 = new Parcel7();
            Contents c = parcel7.contents();
        }
    }

    給匿名內部類傳遞參數時,若該形參在內部類被使用,那麼該形參必須被聲明爲final測試

    public class Parcel9 {
        //dest是一個在外部定義的對象,必須將其定義爲final參數引用
        public Destination destination(final String dest) {
    	return new Destination() {
    	    private String label = dest;
    	    @Override
    	    public String readLabel() {
                    return label;
    	    }
    	};
        }
        public static void main(String[] args) {
    	Parcel9 parcel9 = new Parcel9();
    	Destination destination = parcel9.destination("Shanghai");
    	System.out.println(destination.readLabel());
        }
    }
  9. 爲何要是final?內部類並非直接調用方法傳遞的參數,而是利用自身的構造器對傳入的參數進行備份,本身內部方法調用的其實是本身的屬性而不是外部方法傳遞進來的參數,在內部類中的屬性和外部方法的參數二者看似是同一個東西,但實際上卻不是,也就是說在內部類中對屬性的修改並不會影響到外部的形參,若是內部類中的屬性改變了,而外部方法的形參卻沒有改變,這是難以接受的,爲了保證參數的一致性,就規定使用final來避免二者不一樣時變化的狀況發生。
  10. 每一個類都會產生一個.class文件,其中包含了如何建立該類型的對象的所有信息;內部類也必須生成有個.class文件以包含它們的class對象信息,其命名規則是:

    外圍類的名字,加上」$「,再加上內部類的名字,若是時匿名內部類,編譯器會簡單地產生一個數字做爲其標識符,例如:

    Outer$Inner.class
    Outer$1.class

第十一章 持有對象

  1. Collection是一個集合接口,提供了對集合對象進行操做的通用接口方法
    Collections是一個包裝類,包含有各類集合操做的靜態方法,此類不能實例化,就像一個工具類,服務於Collection框架
    Collection接口是最基本的集合接口,一個Collection表明一組Object,即Collection的元素
  2. List,Set,Queue接口都是Collection接口的實現

    • List:必須按照插入的順序保存元素
    • Set:不能有重複的元素
    • Queue:按照隊列的規則來肯定對象產生的順序(一般與元素插入的順序相同)
  3. 在Java.util包中的Arrays和Collections類中都有不少實用方法,能夠在Collection中添加一組元素;Arrays.asList()方法接受一個數組或是一個用逗號分割的元素列表(使用可變參數),並將其轉換爲一個List對象;Collections.addAll()方法接受一個Collection對象,以及一個數組或是一個用逗號分割的列表,將元素添加到Collection中
    import java.util.*;
    
    public class AddingGroups {
        public static void main(String[] args) {
    	Collection<Integer> collection = 
    	    new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));
    	Integer[] moreInts = {6, 7, 8, 9, 10};
    	collection.addAll(Arrays.asList(moreInts));//更快,但不夠靈活
    	Collections.addAll(collection, 11, 12, 13, 14, 15);
    	Collections.addAll(collection, moreInts);//更加靈活
    	List<Integer> list = Arrays.asList(16, 17, 18, 19, 20);
    	list.set(1, 99);
        }
    }
  4. Arrays相似於Collections,是一個工具類

    Arrays.asList()返回一個受指定數組支持的固定大小的列表,能夠用來將數組轉換成List

    反過來,利用List的toArray()方法,能夠將List轉換成數組

  5. 容器的打印

    必須使用Arrays.toString()來產生數組的可打印表示

  6. List

    ArrayList:隨機訪問,可是在List的中間插入或移除元素時較慢

    LinkedList:經過代價較低的在List中間進行的插入和刪除操做,提供了優化的順序訪問;隨機訪問較慢

    ArrayList常見方法

    contains(Object o):肯定某個對象是否在列表中

    remove(int index):移除指定位置上的元素

    indexOf(Object o):返回列表中首次出現指定元素的索引,若是不包含該元素,返回-1

    add(E e):將制定元素添加到此列表的尾部

    add(int index, E e):將指定元素插入到指定位置

  7. 迭代器是一個對象,它的工做是遍歷並選擇序列中的對象

    Java中的Iterator只能單向移動,只能用來:

    1. 使用方法iterator()要求容器返回一個Iterator;Iterator準備好返回序列的第一個元素
    2. 使用next()得到序列中的下一個元素
    3. 使用hasNext()檢查序列中是否還有元素
    4. 使用remove()將迭代器新近返回的元素刪除
  8. LinkedList常見方法

    addFirst(E e)/addLast(E e):將元素添加到列表的開頭/結尾

    getFirst()/element():返回列表的第一個元素

    peek()/peekFirst():獲取但不移除列表的第一個元素

    offer(E e)/offerLast(E e):將元素插入到列表末尾

  9. Queue

    隊列時一個典型的先進先出(FIFO)的容器,即從容器的一端放入事物,從另外一端取出,而且事物放入容器的順序與取出的順序是同樣的

    LinkedList提供了方法以支持隊列的行爲,而且它實現了Queue接口,所以LinkedList能夠用做Queue的一種實現,也能夠將LinkedList向上轉型爲Queue

  10. Set

    Set不保存重複的元素;Set最常被使用的是測試歸屬性,咱們能夠很容易地詢問某個對象是否在某個Set中

    存儲元素的方式:

    HashSet:使用散列函數

    LinkedHashSet:使用散列,可是看起來使用了鏈表來維護元素的插入順序

    TreeSet:將元素存儲在紅-黑樹結構中

  11. Map:一組成對的「鍵值對」對象,容許使用鍵來查找值;映射表容許咱們使用另外一個對象來查找某個對象,它被稱爲「關聯數組」,由於它將某些對象與另一些對象關聯在了一塊兒,或者被稱爲「字典」

    Map<Integer, Integer> map = new HashMap<Integer, Integer>();

    更復雜的形式

    Map<Integer, List<String>> map = new HashMap<Integer, List<String>>(); map.put(1, rrays.asList("lv", "long", "bao"));

    map的鍵是一個Set,值是一個Collection

    Map常見方法

    get(Object o):返回指定鍵所映射的值,若是不包含該鍵的映射關係,返回null

    put(K key, V value):將指定的值與此映射中的指定鍵關聯,若是已經存在映射關係,更新值

    hashCode():返回此映射的哈希碼值

    Map的三種實現

    HashMap:基於「拉鍊法」實現的散列表,通常用於單線程中,不是線程安全的

    HashTable:基於「拉鍊法」實現的散列表,通常用於多線程中,是線程安全的

    TreeMap:有序的散列表,經過紅黑樹實現的,通常用於單線程中存儲有序的映射

  12. 總結:
    1. 數組將數字與對象聯繫起來:它保存類型明確的對象,查詢對象時,不須要對結果作類型轉換;它能夠時多維的,能夠保存基本類型的數據;可是,數組一旦生成,其容量不能改變
    2. Collection保存單一的元素,而Map保存關聯的鍵值對:有了Java泛型,你就能夠指定容器中存放的對象類型,所以你就不會將錯誤類型的對象放置到容器中,而且在從容器中獲取元素時,沒必要進行類型轉換;各類Collection和Map均可以在你向其中添加更多的元素時,自動調整其尺寸;容器不能持有基本類型,可是自動包裝機制會仔細地執行基本類型到容器中所持有包裝器類型之間的雙向裝換
    3. 像數組同樣,List也創建數字索引與對象的關聯,所以,數組和List都是排好序的容器;List可以自動擴充容量
    4. 若是要進行大量的隨機訪問,就使用ArrayList;若是要常常從表中間插入或刪除元素,則應該使用LinkedList
    5. 各類Queue以及棧的行爲,由LinkedList提供支持
    6. Map是一種將對象(而非數字)與對象相關聯的設計:HashMap設計用來快速訪問;TreeMap保持「鍵」始終處於排序狀態,因此沒有HashMap快;LinkedHashMap保持元素插入的順序,可是也經過散列提供了快速訪問能力
    7. Set不接受重複元素:HashSet提供了最快的查詢速度;TreeSet保持元素處於排序狀態;LinkedHashSet以插入順序保存元素
    8. 新程序中不該該使用過期的Vector,Hashtable和Stack(緣由參考:http://www.javashuo.com/article/p-boyqxxcb-ea.html
相關文章
相關標籤/搜索