【注:此博客旨在從《Java編程思想》這本書的目錄結構上來檢驗本身的Java基礎知識,只爲筆記之用】java
第十一章 持有對象正則表達式
11.1 泛型和類型安全的容器》eg: List<String> 容器中能夠插入該泛型類子類均可以放置進去
11.2 基本概念
(1)Collection. 一個獨立元素的序列,這些元素都服從一條或多條規則.List 必須按照插入的順序保存元素,而Set不能有重複元素
Queue按照排隊規則來肯定對象產生的順序
(2)Map. 一組成對的"鍵值對"對象
11.3 添加一組元素
11.4 容器的打印
ArrayList和LinkedList都是List類型按照插入的順序保存元素;ArrayList優勢在於隨機訪問;LinkedList 優勢在於插入和移除元素
HashSet 按照hash算法插入;TreeSet按照比較的升序保存對象;LinkedHashSet 按照被添加的順序保存對象
11.5 List算法
11.6 迭代器編程
11.6.1 ListIterator》是一個更強大的Iterator的子類型,它只能用於各類List類型的訪問;Iterator只能向前移動,ListIterator能夠
雙向移動。
11.7 LinkedList
11.8 Stack
11.9 Set 》可使用set類型來消除重複元素
11.10 Map
11.11 Queue
11.11.1 PriorityQueue
11.12 Collection和Iterator
11.13 Foreach與迭代器
11.13.1 適配器方法慣用法數組
第十二章 經過異常處理錯誤緩存
12.1 概念
12.2 基本異常
12.3 捕獲異常
12.3.1 try塊
12.3.2 異常處理程序
12.4 建立自定義異常
12.4.1 異常與記錄日誌
12.5 異常說明》在編譯時強制檢查的異常被稱爲被檢查異常
12.6 捕獲全部異常》catch exception
12.6.1 棧軌跡
12.6.2 從新拋出異常 》throw
12.6.3 異常鏈》Throwable的子類中三種基本異常類提供了帶cause參數的構造器:Error(Java虛擬機報告系統錯誤),Exception以及
RuntimeException安全
12.7 Java標準異常》Throwable 表示任何能夠做爲異常被拋出的類。Throwable對象能夠分爲兩種類型:Error表示編譯時和系統錯誤(除
特殊狀況外,通常不用關心);Exception 表示被拋出的異常的基本類型,在Java類庫,用戶方法以及運行時故障中均可能拋出Exception。Java
開發人員關心的基本類型一般是Exception。
12.7.1 特例:RuntimeException
12.8 使用finally進行清理
12.8.1 finally用來作什麼
12.8.2 在return中使用finally
12.8.3 缺憾:異常丟失
12.9 異常的限制
12.10 構造器
12.11 異常匹配
12.12 其餘可選方式
12.12.1 歷史
12.12.2 觀點
12.12.3 把異常傳送給控制檯
12.12.4 把「被檢查的異常」轉換爲「不檢查的異常」》throw new RuntimeException(e);
12.13 異常使用指南
(1)在恰當的級別處理問題(在知道該如何處理的狀況下才捕獲異常)
(2)解決問題而且從新調用產生異常的方法
(3)進行少量的修補,而後繞過異常發生的地方繼續執行
(4)用別的數據進行計算,以替代方法預計會返回的值
(5)把當前運行環境下能作的事情儘可能作完,而後把相同的異常從新拋到更高層
(6)把當前運行環境下能作的事情儘可能作完,而後把不一樣的異常拋到更高層
(7)終止程序
(8)進行簡化(若是你的異常模式使問題變得太複雜,那用起來會很是痛苦)
(9)讓類庫和程序更安全架構
第13章 字符串app
13.1 不可變String
13.2 重載「+」與StringBuilder》當在Java中作字符串相加"+"時,底層會自動引入iava.lang.StringBuilder類
StringBuilder與StringBuffer相比較,後者是線程安全的
13.3 無心識的遞歸
13.4 String上的操做
13.5 格式化輸出
13.5.1 printf()
13.5.2 System.out.format()
13.5.3 Formatter類
13.5.4 格式化說明符》其抽象語法:%[argument_index$][flags][width][.precision]conversiondom
13.5.5 Formatter轉換
13.5.6 String.format()
13.6 正則表達式
13.6.1 基礎
13.6.2 建立正則表達式
13.6.3 量詞
13.6.4 Pattern和Matcher
13.6.5 split()
13.6.6 替換操做
13.6.7 reset()
13.6.8 正則表達式與Java I/O》正則表達式搜索文件的內容
13.7 掃描輸入》Scanner
13.7.1 Scanner定界符
13.7.2 用正則表達式掃描
13.8 StringTokenizer》可使用Scanner或正則表達式替代
第14章
14.1 爲何使用RTTI》(RTTI:在運行時識別一個對象的類型)
14.2 Class對象》Java使用Class對象來執行其RTTI,即便你正在執行的是相似轉型的操做
每一個類都有一個Class對象;使用「類加載器」來生成類對象;類是在第一次使用時動態加載到JVM中的
獲取Class對象:Class.forName() ;對象.getClass(); Class對象的newInstance()建立類對象,該類必須帶有默認的構造器
14.2.1 類字面常量》獲取Class對象的另外一個方法:類名.class 如:String.class。使用這種方式不會自動初始化該Class對象
爲了使用類而坐的準備工做包含三步驟:
(1)加載,這是有類加載器執行的
(2)連接 在連接階段將驗證類中的字節碼,爲靜態域分配存儲空間,而且若是必要的話,將解析這個類建立對其餘類的引用
(3)初始化 若是該類具備超類,則對其初始化,執行靜態初始化器和靜態初始化塊
因此,初始化操做被延遲到對靜態方法(構造器隱式是靜態的)或者很是態數靜態進行首次引用時才執行
14.2.2 泛化的Class引用》Class<T>
Class<?> 優於普通的Class,儘管它們等價,可是Class<?>不會產生編譯器警告信息;
Class<?>的好處是它表示你並不是是碰巧或因爲疏忽,而是使用了一個非具體的類引用
14.2.3 新的轉型語法》Class對象.cast()
Class中兩個使用不常使用或沒有任何用處的新特性是:Class對象.cast()接受參數對象並將其轉換爲Class引用的類型;
Class.asSubclass()容許你將一個類對象轉型爲更加具體的類型。
14.3 類型轉換前先作檢查》instanceof; class<? extends 基類>
14.3.1 使用類字面常量》類名.class
14.3.2 動態的instanceof》Class.isInstance方法提供了一種動態測試對象的途徑
14.3.3 遞歸計數
14.4 註冊工廠
14.5 instanceof 與 Class的等價性
14.6 反射:運行時的類信息》RTTI(Run-Time Type Identification)和反射之間真正的區別在於:對於RTTI來講,編譯器在編譯時
打開和檢查.class文件。而對於反射機制來講,.class文件在編譯時是不能夠獲取的,因此在運行時開發和檢查.class文件
14.6.1 類方法提取器》Class的getMethods()和getConstructors()方法分別返回Method對象數組和Constructor對象數組
14.7 動態代理
14.8 空對象
14.8.1 模擬對象與樁
14.9 接口與類型信息》javap一個隨JDK發佈的反編譯器
javap -private 類名 》eg:javap -private java.lang.String
14.10 總結反射式強大的,能夠經過修改權限調用哪些被設置成private的方法
第15章 泛型
15.1 與C++比較
15.2 簡單泛型》Java泛型的核心概念是告訴編譯器想要什麼類型,而後編譯器幫你處理一切細節
泛型的主要目的是用來指定容器要持有什麼類型的對象,而且有編譯器來保證類型的正確性
public class Generate<T>{ private T t; Generate(T t){ this.t=t;} }
15.2.1 一個元組類庫
須要在一個方法就能返回多個不一樣類型的對象,但是return 語句只容許返回單個對象,解決辦法就是再建立一個對象,
用它來包含想要返回的多個類型對象,當能夠在每次須要的時候專門建立一個類爲此工做,可是有了泛型咱們就可以一次性解決
這個問題,同時咱們還能再編譯器確保類型的安全。這個概念就是元組(tuple),它將多個對象存儲在一個單一對象中,這個容器
對象容許讀取其中的元素,可是不容許向其中存放新的對象。元組能夠任意長度,以下兩個類型的元組:
public class TwoTuple<A,B>{//這個類能夠裝載兩個類型的 public finale A first; public finale B second; TwoTuple(A a,B b){ this.first=a; this.second=b; } } public class TestTuple{ static TwoTuple<String,Integer> f(){//該方法就返回了String,Integer兩種類型的對象 return new TwoTuple<String,Integer>("hi",70); } public static void main(String[] args){ f(); } }
15.2.2 一個堆棧類
15.2.3 RandomList
15.3 泛型接口
public interface Generator<T> {T next();} public class Fibonaci implements Generator<Integer>{ private int count=0; public Integer next(){return fib(count++);} private Integer fib(int n){ if(n<2)return 1; return fib(n-2)+fib(n-1); } public static void main(String[] args){ Fibonaci f=new Fibonaci(); for(int i=0;i<10;i++){ System.out.println(f.next()); } } }
15.4 泛型方法 》要定義泛型方法只須要將泛型參數置於返回值以前
public class GenericMethods{ public <T> void f(T t) { System.out.println(t.getClass().getSimpleName()); } public static void main(String[] args) { GenericMethods chapterA = new GenericMethods(); chapterA.f(""); } }
15.4.1 槓桿利用類型參數推斷
顯示的類型說明:點操做符與方法名之間插入尖括號,而後把類型置於尖括號內
若是是在定義該方法類的內部,必須在點操做符以前使用this關鍵字
若是使用的static方法,必須在點操做符以前加上類名
public class ExplicitTypeSpecification{ static void f(Map<Person,List<Pet>> petPeople){} public static void(String[] args){ f(XXXX.<Person,List<Pet>>map()); } }
15.4.2 可變參數與泛型方法
public class GenericVarargs{ public static <T> List<T> makeList(T... args){ List<T> result=new ArrayList<T> (); for(T item: args){ result.add(item); } return result; } public static void main(String[] args){ List<String> ls=makeList("A"); System.out.println(ls); ls=makeList("A","B","C"); System.out.println(ls); } }
15.4.3 用於Generator的泛型方法
15.4.4 一個通用的Generator
15.4.5 簡化元組的使用
public class Tuple{ public static <A,B> TwoTuple<A,B> tuple(A a,B b){ return new TwoTuple<A,B>(a,b); } }
15.4.6 一個Set使用工具
15.5 匿名內部類
class Teller{ private static long counter=1; private final long id=counter++; public String toString(){return "Teller "+id;} public static Generator<Teller> generator=new Generator<Teller>(){....} }
15.6 構建複雜模型
public class TupleList<A,B,C,D> extends ArrayList<A,B,C,D>{ public static void main(String[] args){ TupleList<Vehicle,Amphibian,String,Integer> tl=new TupleList<Vehicle,Amphibian,String,Integer>(); ..... } }
15.7 擦除的神祕之處
public class ErasedTypeEquivalence{ public static void main(String[] args){ Class c1 = new ArrayList<String>().getClass(); Class c2 = new ArrayList<Integer>().getClass(); System.out.println(c1 == c2); } }
輸入的結果是:true
在這裏咱們很容易的認爲ArrayList<String>和ArrayList<Integer>是不一樣的類型,即輸出的結果爲false,但是Java運行
出來的結果是true,這說明Java認爲他們是同一個類型,爲何呢?
在看爲何錢,咱們先來看看Class類中的getTypeParameters這個方法的定義和做用
註釋的意思是:返回一個TypeVariable類型的數組,TypeVarible表示泛型中使用的類型變量或者類型參數
/** * Returns an array of {@code TypeVariable} objects that represent the * type variables declared by the generic declaration represented by this * {@code GenericDeclaration} object, in declaration order. Returns an * array of length 0 if the underlying generic declaration declares no type * variables. * * @return an array of {@code TypeVariable} objects that represent * the type variables declared by this generic declaration * @throws java.lang.reflect.GenericSignatureFormatError if the generic * signature of this generic declaration does not conform to * the format specified in * <cite>The Java™ Virtual Machine Specification</cite> * @since 1.5 */ @SuppressWarnings("unchecked") public TypeVariable<Class<T>>[] getTypeParameters() { ClassRepository info = getGenericInfo(); if (info != null) return (TypeVariable<Class<T>>[])info.getTypeParameters(); else return (TypeVariable<Class<T>>[])new TypeVariable<?>[0]; }
再看以下程序:
咱們看到輸入的並非具體的類型名,而是隻是無用的佔位符的標識符
所以,這說了一個現實是:在泛型代碼的內部,沒法得到任何有關泛型參數類型的信息
15.7.1 C++的方式》模板被實例化時,模板代碼知道其模板參數的類型
可是針對泛型的擦除能夠用extends 定義一個上限:List<T extends Parent>,那麼編譯器在進行泛型類型參數
擦除時將擦除到它的第一個邊界,即就像「Parent」替換「T「同樣
15.7.2 遷移兼容性
爲了減小潛在的關於擦除的混淆,必須清楚的認識到這不是一個語言的特性.它是Java泛型實現的一種折中,由於泛型不是
在Java語言一開始出現時就有的;若是泛型在Java 1.0中就已經有了,那麼這個特性就不會使用擦除來實現了。擦除減小了泛
型的泛化性,雖然泛型仍然頗有用,只是沒有咱們想象的那麼有用了
在基於擦除的現實中,泛型類型被看成第二類類型處理,即不能在某些重要的上下文環境中使用的類型。泛型只在靜態類型
檢查期間纔出現,在此以後,程序中全部的泛型類型都將被擦除,替換爲它們的非泛型上界。例如:List<T> 將爲擦除爲List,
而普通的類型變量,在未經過"extends"指定上限狀況下將被擦除爲Object
擦除機制的核心動機是使採用泛化的代碼可使用費泛化的代碼
15.7.3 擦除的問題
擦除的主要正當理由是從非泛化代碼到泛化代碼的轉變過程,以及不破壞現有的類庫的狀況下,將泛型融入Java語言
其代價就是:不能用於顯示的引用運行時類型的操做中,如轉型,instanceof操做和new 表達式;由於全部的參數類型信息
都丟失了。因此,不管什麼時候,當你在編寫泛型代碼時,必須時刻提醒本身,這些只是看起來好像擁有關於參數的類型信息
15.7.4 邊界處的動做
15.8 擦除的補償
15.8.1 建立類型實例
15.8.2 泛型數組》因爲泛型擦除》因此通常的解決方案是在任何想要建立泛型數組的地方都是用ArrayList
15.9 邊界》 xxx<T extends SuperClass>
或class ColoredDimension<T extends Dimension&HashColor>{}
或class ColoredDimension<T extends Dimension & HashColor & Weight>{}
或
class HoleItem<T>{}
class Colored<T extends HasColor> extends HoleItem<T>{}
15.10 通配符》class Demo<? extends Uper>
15.10.1 編譯器有多聰明》編譯器並無想象中的那麼聰明
public class CompilerIntellience{ List<? extends Fruit> flist=Arrays.asList(new Apple()); Apple a=(Apple)flist.get(0);//沒有警告 flist.contains(new Apple()); //Argument is "Object" flist.indexOf(new Apple()); //Argument is "Object" }
15.10.2 逆變》超類通配符:super
public class SuperTypeWildcards{ static void wirteTo(List<? super Apple> apples){ apples.add(new Apple()); apples.add(new Jonathan()); //apples.add(new Fruit()); //Error } }
15.10.3 無界通配符》?
public class UnboundedWildcards{ static Map map1; static Map<?,?> map2; static Map<String,?> map3; }
List和List<?>是不一樣的:List能夠持有任何類型的組合,而List<?>將持有具備某種具體類型的同構集合
在使用確切類型替代通配符類型的好處是能夠用泛型參數來作更多的事,可是使用通配符使得你必須接受範圍更寬的參數化類型做爲參數
15.10.4 捕獲轉換
15.11 問題
15.11.1 任何基本類型都不能做爲類型參數
15.11.2 實現參數化接口》一個類不一樣實現同一個泛型接口的兩中變體,因爲擦除的緣由,這兩個變體會成爲相同的接口
interface Payable<T>{} class Employee implements Payable<Employee>{} class Hourly extends Employee implements Payable<Horly> {} //這個類不能編譯,由於擦除會將Payable<Horly>和Payable<Employee>簡化爲相同的類Payable,這樣就意味着 //在重複兩次實現相同的接口
15.11.3 轉型和警告》使用帶有泛型參數的轉型或instanceof不會有任何效果
15.11.4 重載
public class UserList<W,T>{ void f(List<T> v){} void f(List<W> v){} }//因爲擦除的緣由,重載方法產生相同的方法簽名,所以當擦除的參數不能產生惟一的參數列表時,必須提供明顯的區別: public class UserList<W,T>{ void f1(List<T> v){} void f2(List<W> v){} }
15.11.5 基類劫持了接口
15.12 自限定的類型
15.12.1 古怪的循環類型
15.12.2 自限定
自限定所作的就是要求在繼承關係中下面這樣定義:
class A extends SelfBounded<A>{}
這回強制要求將正在定義的類看成參數傳遞給基類
其意義保證類型參數必須與正在定義的類相同
15.12.3 參數協定
15.13 動態類型安全
將子類的類型的對象放置到將要檢查基類類型的受檢查容器中是沒有問題的
15.14 異常
因爲擦除緣由,泛型應用於異常是很是有限的.catch語句不能捕獲泛型類型的異常,由於在編譯器和運行時都必須知道異常的確切類型.
泛型也不能直接或間接繼承自Throwable.可是泛型參數可能會在一個方法的throws字句中用到.這可讓你編寫隨檢查型異常的類型而
發生變化的泛型代碼
interface Processor<T, E extends Exception> {}
15.15 混型
混型最基本的概念是混合多個類的能力以產生一個能夠表示混型中全部類型的類,其價值之一是能夠將特性和行爲一致的應用於多個類中.
若是想在混型總修改某些東西,這些修改將會應用於混型所應用的全部類型之上.
15.15.1 C++中的混型
15.15.2 與接口混合
interface Basic{ private String value; public void set(String val); public String get(); } interface SerivalNumbered{long getSerialNumber();} interface TimeStamped{long getStamp();} class BasicTmp implements Basic{ private String value; public void set(String val){value=val;} public String get(){return value;} } class Mixin extends BasicTmp implements SerivalNumbered,TimeStamped{ .... }
15.15.3 使用裝飾器模式
15.15.4 與動態代理混合
15.16 潛在類型機制》不要求靜態或動態類型檢查
在Java中由於泛型是後期才添加到Java中的,所以沒有任何機會能夠去實現任何類型的潛在類型機制,所以Java不支持這種特性
15.17 對缺少潛在類型機制的補償
15.17.1 反射》可使用反射來實現相似的潛在類型機制的特性
15.17.2 將一個方法應用於序列
15.17.3 當你並未碰巧擁有正確的接口時
15.17.4 用適配器仿真潛在的類型機制
15.18 將函數對象用做策略
15.19 總結:轉型真的如此之遭嗎?
15.19.1 進階讀物
第16章
16.1 數組爲何特殊
在泛型和自動包裝機制以前,數組與其餘容器之間的區別有三方面:效率,類型和保存基本類型的能力
在Java中數組是一種效率最高的存儲和隨機訪問對象引用序列的方式,它是簡單的線性序列,這使得訪問的速度很是快速,
可是這種快速所付出的代價就是數組對象的大小被固定了,而且在生命週期中不可改變。
隨着自動包裝機制的出現,如今容器能夠與數組同樣方便的用於基本類型,數組惟一的優勢就是效率
16.2 數組是以第一級對象》數組標識符其實只是一個引用
16.3 返回一個數組
16.4 多維數組
16.5 數組與泛型
class ClassParameter<T>{//參數化類 public T[] f(T[] arg){return arg;} } class MethodParameter{//參數化方法 public static <T> T[] f(T[] arg){return arg;} } public class ParameterArrayType{ public static void main(String[] args){ Integer[] ints={1,2,3,4}; Double[] doubles={1.1,2.2,3.3,4.4,5.5}; Integer[] ints2=new ClassParameter<Integer>().f(ints); Double[] double2=new ClassParameter<Double>().f(doubles); } }
Peel<Banana>[] peels=new Peel<Banana>[10];//報錯
儘管不能建立實際的持有泛型的數組對象,可是能夠建立非泛型的數組
List<String>[] ls;
List[] la=new List[20];
ls=(List<String>)la;//"Unchecked" warning
通常而言,泛型在類或方法的邊界處頗有效,而在類或方法的內部,擦除一般會是泛型變得不適用
16.6 建立測試數據
16.6.1 Arrays.fill()
16.6.2 數據生成器
16.6.3 從Genenrator中建立數組
16.7 複製數組
16.7.1 複製數組》System.arraycopy()
16.7.2 數組的比較》Arrays.equals()
16.7.3 數組元素比較》java.lang.Comparable接口 ; compareTo()方法
16.7.4 數組排序》Arrays.sort()
16.7.5 在已排序的數組中查找》Arrays.binarySearch()
第17章 容器深刻研究
17.1 完整的容器分類法
17.2 填充容器》Collections.nCopies() ;Collections.fill()
17.2.1 一種Generator解決方案
17.2.2 Map生成器
17.2.3 使用Abstract類
17.3 Collection的功能方法
17.4 可選操做
17.4.1 爲獲支持的操做》Arrays.asList()會生成一個基於固定大小數組的List
注意:Arrays.asList()的結果做爲構造器的參數傳遞給任何Collection(或者使用
addAll()方法,或Collections.addAll()靜態方法),這樣能夠生成容許使用全部方法的普通容器
17.5 List的功能方法
17.6 Set和存儲順序
在HashSet上打星號表示,若是沒有其餘限制,它就是默認的選擇,由於它對速度進行了優化
17.6.1 SortedSet
17.7 隊列
17.7.1 優先級隊列
17.7.2 雙向隊列
17.8 理解Map
17.8.1 性能
17.8.2 SortedMap》鍵處於排序狀態
17.8.3 LinkedHashMap
17.9 散列與散列碼》自定義類重載hashCode()和equals()
17.9.1 理解hashCode()
17.9.2 爲速度而散列
17.9.3 覆蓋hashCode()
17.10 選擇接口的不一樣實現
17.10.1 性能測試架構
17.10.2 對List的選擇
17.10.3 微基準測試的危險
17.10.4 對Set的選擇
17.10.5 對Map的選擇
17.11 實用方法
17.11.1 List的排序和查詢》使用Collections中的方法 17.11.2 設定Collection或Map爲不可修改》Collections.unmodifiableCollection(c) 17.11.3 Collections或Map的同步控制》Collections.synchronizedCollection(c) ConcurrentHashMap、CopyOnWriteArrayList和CopyOnWriteArraySet都使用了能夠避免ConcurrentModificationException的技術17.12 持有引用 對象可得到則垃圾回收器不會釋放它;若不可得到,那麼回收就是安全 SoftReference、WeakReference和PhantomReference由強到弱排序,對應不一樣級別的「可得到性」.SoftReference用以實現內存敏感的高速緩存。WeakReference是爲實現「規範映射」而設計的,它不妨礙垃圾回收器回收映射的「鍵」。「規範映射」中的對象的實例能夠在程序的多處被同時使用,以節省存儲空間。PhantomReference用以調度回收器前的清理工做,它比Java終止機制更靈活。 PhantomReference只能依賴於ReferenceQueue 17.12.1 WeakHashMap》它被用來保存WeakReference17.13 Java 1.0/1.1的容器 17.13.1 Vector和Enumeration 17.13.2 Hashtable 17.13.3 Stack 17.13.4 BitSet