Java面向對象知識點拆分(二)
Java面向對象的編程思想是極其重要的,可以說是Java的核心,這塊內容比較細,比較多,花了兩周時間,整理出來 47 條知識點,幫助大家穩固基礎,早日實現年薪百萬,哈哈~
下面是后半部分,前一部分請戳這里
定義:是對問題的描述,將問題進行對象的封裝。指程序在運行時出現不正常情況。
由來:問題也是現實生活中一個具體的事物,也可以通過Java的類的形式進行描述。并封裝成對象。其實就是Java對不正常情況進行描述后的對象體現。
對于問題的劃分:嚴重的問題、非嚴重的問題。
對于嚴重的,Java通過Error類進行描述;對于Error一般不編寫針對性的代碼對其進行處理。對于非嚴重的,Java通過Exception類進行描述。對于Exception可以使用針對性的處理方式進行處理。
無論Error或者Exception都具備一些共性內容。比如:不正常情況的信息,引發原因等。
對捕獲到的異常對象進行常見方法操作:
String getMessage():獲取異常信息。
在函數上聲明異常,便于提高安全性,讓調用出進行處理。不處理編譯失敗。
對多異常的處理:
①聲明異常時,建議聲明更為具體的異常,這樣處理的可以更具體。②對方聲明幾個異常,就對應有幾個catch塊,不要定義多余的catch塊。如果多個catch塊中的異常出現繼承關系,父類異常catch塊放在最下面。
建立在進行catch處理時,catch中一定要定義具體處理方式。不要簡單的就書寫一條輸出語句。
當在函數內部出現了throw拋出異常對象,那么就必須要給對應的處理動作。要么在內部try catch處理。要么在函數上聲明讓調用者處理。一般情況下,函數內出現異常,函數上需要聲明。
如何定義異常信息?
因為父類中已經把異常信息的操作都完成了。所以子類只要在構造時,將異常信息傳遞給父類通過super語句。那么就可以直接通過getMessage方法獲取自定義的異常信息。
自定義異常:
必須是自定義類繼承Exception。自定義異常時,如果該異常的發生,無法再繼續進行運算,就讓自定義異常繼承RuntimeException。
繼承Exception原因:
異常體系有一個特點:因為異常類和異常對象都被拋出。他們都具備可拋性。這個可拋性是Throwable這個體系中獨有特點。
只有這個體系中的類和對象才可以被throws和throw操作。
當要定義自定義異常的信息時,可以使用父類已經定義好的功能。將異常信息傳遞給父類的構造函數。
class MyException extends Exception{ MyException(String message){ super(message); } }
自定義異常:按照java的面向對象思想,將程序中出現的特有問題進行封裝。
throw和throws的區別:
throws使用在函數上。后面跟的異常類。可以跟多個;用逗號隔開。
throw使用在函數內。后跟的是異常對象。
注意:
Exception中有一個特殊的子類異常RuntimeException(運行時異常)。如果在函數內容拋出該異常,函數上可以不用聲明,編譯一樣通過。如果在函數上聲明了該異常,調用者可以不用進行處理,編譯一樣通過。之所以不用在函數上聲明,是因為不需要讓調用者處理。當該異常發生,希望程序停止。因為在運行時,出現了無法繼續運算的情況,希望停止程序后,讓程序員對代碼進行修正。
對于異常分兩種:
①編譯時被檢測的異常:
該異常在編譯時,如果沒有處理(沒有拋也沒有try),編譯失敗。該異常被標識,代表這可以被處理。
②編譯時不被檢測的異常(運行時異常。RuntimeException以及其子類)
在編譯時,不需要處理,編譯器不檢查。該異常的發生,建議不處理,讓程序停止,需要對代碼進行修正。
finally代碼塊:
①定義一定執行的代碼。通常用于關閉資源,因為資源必須釋放。
②finally只有一種情況不會執行。當執行到System.exit(0);finally不會執行。
try_catch_finally格式:
①try{}catch(){}
②try{需要被檢測的代碼}catch(){處理異常的代碼}finally{一定會被執行的代碼}
③try{}finally{}
catch是用于處理異常。如果沒有catch就代表異常沒有被處理過,如果該異常是檢測時異常,那么必須聲明。
異常在子類覆蓋中的體現:
①子類在覆蓋父類時,如果父類的方法拋出異常,那么子類的覆蓋方法,只能拋出父類的父類的異常或者該異常的子類。②如果父類方法拋出多個異常,那么子類在覆蓋該方法時,只能拋出父類異常的子集。③如果父類或者接口的方法中沒有異常拋出,那么子類在覆蓋方法時也不可以拋出異常。如果子類方法發生了異常,就必須要進行try處理,絕對不能拋。
異常體系的特點:
異常體系中的所有類以及建立的對象都具備可拋性。也就是說可以被throw和throws關鍵字所操作。只有異常體系具備這個特點。
當函數內容有throw拋出異常對象,并未進行try處理。必須要在函數上聲明,否則編譯失敗。注意,RuntimeExceptin除外,也就說,函數內如果拋出的RuntimeException異常,函數上可以不用聲明。
如果函數聲明了異常,調用者需要進行處理。處理方法可以throws可以try。
異常的好處:
①將問題進行封裝;
②將正常流程代碼和問題處理代碼相分離,方便于閱讀。
異常的處理原則:
①處理方式有兩種:try或者throws;
②調用到拋出異常的功能時,拋出幾個,就處理幾個。一個try對應多個catch。
③多個catch,父類的catch放到最下面;
④catch內,需要定義針對性的處理方式,不需要簡單的定義printStackTrace,輸出語句。也不要不寫。當捕獲到的異常,本功能處理不了時,可以繼續在catch中拋出。
try{ throw new AException(); }catch(AException e){ throw e; }
如果該異常處理不了,但并不屬于該功能出現的異常。可以將異常轉換后,再拋出和該功能相關的異常。
或者異常可以處理,當需要將異常產生的和本功能相關的問題提供出去,讓調用者知道,并處理。也可以將捕獲異常處理后,轉換新的異常。
try{ throw new AException(); }catch(){ //對AException處理 throw new BException(); }
比如:匯款的例子。
異常的注意事項:
在子父類覆蓋時:
①子類拋出的異常必須是父類的異常的子類或者子集。
②如果父類或者接口沒有異常拋出時,子類覆蓋出現異常,只能try不能拋。
參閱例子:
老師用電腦上課、圖形面積。
總結:
包與包之間進行訪問,被訪問的包中的類以及類中的成員,需要public修飾。 不同包中的子類還可以直接訪問訪問父類中被protected權限修飾的成員。
包與包之間可以使用的權限只有兩種,public protected。
權限修飾符:
進程:是一個正在執行中的程序。每一個進程執行都有一個執行順序。該順序是一個執行路徑,或者叫一個控制單元。
線程定義:就是進程中的一個獨立的控制單位。線程在控制著進程的執行。一個進程中至少有一個線程。(Thread:一個程序里面不同執行路徑)。
擴展知識:
其實更細節說明jvm,jvm啟動不止一個線程,還有負責垃圾回收機制的線程。
創建線程的方式:
第一種方式:繼承Thread類
步驟:
①定義類繼承Thread;
②復寫Thread類中的run方法;
目的:將自定義代碼存儲在run方法。讓線程運行。
③調用線程的start方法;該方法有兩個作用:啟動線程,調用run方法。
為什么要覆蓋run方法呢?
Thread類用于描述線程。該類就定義了一個功能,用于存儲線程要運行的代碼。該存儲功能就是run方法。也就是說Thread類中的run方法,用于存儲線程要運行的代碼。
第二種方式:實現Runnable接口
步驟:
①定義類實現Runnable接口;
②覆蓋Runnable接口中的run方法;
將線程要運行的代碼放在該run方法中。
③通過Thread類建立線程對象;
④將Runnable接口的子類對象作為實際參數傳遞給Thread類的構造函數。
因為,自定義的run方法所屬的對象是Runnable接口的子類對象,所以要讓線程去執行指定對象的run方法。
⑤調用Thread類的start方法開啟線程并調用Runnable接口子類的run方法。
實現方式和繼承方式有什么區別呢?
實現方式好處:
避免了單繼承的局限性。在定義線程時,建議使用實現方式。
兩種方式區別:
繼承Thread:線程代碼存放Thread子類run方法中。
實現Runnable:線程代碼存在接口的子類的run方法中。
多線程特性:
隨機性:誰搶到誰執行,至于執行多長,cpu決定。
static Thread currentThread():獲取當前線程對象。
getName():獲取線程名稱。
設置線程名稱:setName或者構造函數。
Java對于多線程的安全問題提供了專業的解決方式——同步代碼塊。
synchronized(對象){ 需要被同步的代碼 }
對象如同鎖。持有鎖的線程可以在同步中執行。沒有持有鎖的線程即使獲取cpu的執行權,也進不去,因為沒有鎖。
同步的前提:
①必須要有兩個或者兩個以上的線程;
②必須是多個線程使用同一個鎖。
必須保證同步中只能有一個線程在運行。
同步的好處:
解決了多線程的安全問題。
同步的弊端:
多個線程需要判斷鎖,較為消耗資源。
同步函數用的是哪一個鎖呢?
函數需要被對象調用。那么函數都有一個所屬對象引用。就是this。所以同步函數使用的鎖是this。
如果同步函數被靜態修飾后,使用的鎖是什么呢?
通過驗證,發現不再是this。因為靜態方法中也不可以定義this。
靜態進內存時,內存中沒有本類對象,但是一定有該類對應的字節碼文件對象。類名.class。該對象的類型是Class。
靜態的同步方法,使用的鎖是該方法所在類的字節碼文件對象。類名.class。
線程間通訊:
其實就是多個線程在操作同一個資源,但是操作的動作不同。
wait();notify();notifyAll()都是用在同步中,因為要對持有監視器(鎖)的線程操作。所以要使用在同步中,因為只有同步才具有鎖。
為什么這些操作線程的方法要定義在Object類中呢?
因為這些方法在操作同步中線程時,都必須要標識他們所操作線程持有的鎖。只有同一個鎖上的被等待線程,可以被同一個鎖上notify()喚醒。不可以對不同鎖中的線程進行喚醒。也就是說,等待和喚醒必須是同一個鎖。而鎖可以是任意對象,所以可以被任意對象調用的方法定義在Object類中。
如何停止線程?
只有一種方式,run方法結束。
分析:
開啟多線程運行,運行代碼通常是循環結構。只要控制住循環就可以讓run方法結束,也就是線程結束。
特殊情況:
當線程處于凍結狀態,就不會讀取到標記,那么線程就不會結束。
當沒有指定的方式讓凍結的線程恢復到運行狀態時,這時需要對凍結進行清除。
強制讓線程恢復到運行狀態中來。這樣就可以操作標記讓線程結束。
Thread類提供該方法interrupt();
join()方法:
當A線程執行到了B線程的.join()方法時,A就會等待。等B線程都執行完,A才會執行。
join可以用來臨時加入線程執行。
String s1 = "abc";
s1是一個類類型變量,"abc"是一個對象。字符串最大特點:一旦被初始化就不可以被改變。
String s2 = new String("abc");
s1和s2有什么區別?
s1在內存中有一個對象。s2在內存中有兩個對象。
常見的操作:
獲取:
1.1 字符串中的包含的字符數,也就是字符串的長度。
int length():獲取長度。
1.2 根據位置獲取位置上某個字符。
char charAt(int index)
1.3 根據字符獲取該字符在字符串中位置。
int indexOf(int ch):返回的是ch在字符串中第一次出現的位置。
int indexOf(int ch, int fromIndex):從fromIndex指定位置開始,獲取ch在字符串中出現的位置。
int indexOf(String str):返回的是str在字符中第一次出現的位置。
int lastIndexOf(String str, int fromIndex):從fromIndex指定位置開始,獲取str在字符串中出現的位置。
判斷:
2.1 字符串中是否包含某一個子串。
boolean contains(str)
特殊之處:indexOf(str):可以索引str第一次出現位置,如果飯回-1,標識該str不在字符串中存在。所以,也可以用于對指定判斷是否包含。if(str.indexOf(“aa”)!=-1)而且該方法既可以判斷,又可以獲取出現的位置。
2.2 字符中是否有內容。
boolean isEmpty():原理就是判斷長度是否為0.
2.3 字符串是否是以指定內容開頭。
boolean starWith(str);
2.4 字符串是否是以指定內容結尾。
boolean endsWith(str);
2.5 判斷字符串的內容是否相同。復寫了Object類中的equals方法。
boolean equalsIgnoreCase();
轉換:
3.1 將字符數組轉換成字符串。
構造函數:String(char[])
String(char[], offset, count):將字符數組中的一部分轉成字符串。
靜態方法:
static String copyValueOf(char[]);
static String copyValueOf(char[] data, int offset, int count)
static String valueOf(char[]):
3.2 將字符串轉成字符數組。
char[] toCharArray();
3.3 將字節數組轉成字符串。
String(byte[])
String(byte[], offset, count):將字節數組中的一部分轉換成字符串。
3.4 將字符串轉成字節數組。
byte[] getBytes();
3.5 將基本數據類型轉成字符串。
static String valueOf(int)
static String valueOf(double)
特殊:字符串和字節數組在轉換過程中,是可以指定編碼表的。
替換:
String replace(oldchar, newchar);
切割:
String[] split(regex);
子串:
獲取字符串中的一部分。
String substring(begin);從指定位置開始到結尾。如果角標不存在,會出現角標越界異常。
Striing substring(begin,end);包含頭,不包含尾。
轉換,去除空格,比較
7.1 將字符串轉成大寫或者小寫。
String toUpperCase();
String toLowerCase();
7.2 將字符串兩端的多個空格去除。
String trim();
7.3 對兩個字符串進行自然順序的比較。
int compareTo(string);
是字符串緩沖區。是一個容器,而且長度是可以變化的。
常見操作:
存儲:
StringBuffer append():將指定數據作為參數添加到已有數據結尾處。
StringBuffer insert(index,數據):可以將數據插入到指定index位置。
刪除:
StringBuffer delete(start,end):刪除緩沖區中的數據,包含start,不包含end。
StringBuffer deleteCharAt(index):刪除指定位置的字符。
獲取:
char charAt(int index):返回此序列中指定索引處的 char 值
int indexOf(String str):取出給定字符串的索引
int lastIndexOf(String str): 返回最右邊出現的指定子字符串在此字符串中的索引。
int length():字符串的長度
String substring(int start, int end):返回一個新的 String,它包含此序列當前所包含的字符子序列。
修改:
StringBuffer replace(start,end,string):使用給定 String 中的字符替換此序列的子字符串中的字符。
void setCharAt(int index, char ch):將給定索引處的字符設置為 ch。
反轉:
StringBuffer reverse():將此字符序列用其反轉形式取代。
將緩沖區中指定數據存儲到指定字符數組中。
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) :將字符從此序列復制到目標字符數組 dst。
JDK1.5版本之后出現了StringBuilder.
StringBuffer是線程同步。
StringBuilder是線程不同步。
開發中建議使用StringBuilder
升級三個因素:
①提高效率②簡化書寫③提高安全性。
基本數據類型對象包裝類
byte——Byte
short——Short
int——Integer
long——Long
float——Float
double——Double
char——Character
boolean——Boolean
基本數據類型對象包裝類的最常見作用:用于基本數據類型和字符串類型之間的轉換。
基本數據類型轉換成字符串。
基本數據類型+"";
基本數據類型.toString(基本數據類型值);
如:Integer.toString(34);//將整數34轉換成"34".
字符串轉換成基本數據類型。
xxx a = Xxx.parseXxx(String); int a = Integer.parseInt("15"); double b = Double.parseDouble("55.50"); boolean b = Boolean.parseBoolean("true"); public int intValue() // 以 int 類型返回該 Integer 的值。 Integer i = new Integer("123"); int num = i.intValue();//這是個非靜態方法,要建立對象調用。
十進制轉成其他進制。
toBinaryString();
toHexString();
toOctalString();
其他進制轉十進制。
parseInt(string,radix) 使用第二個參數指定的基數,將字符串參數解析為有符號的整數。
JDK1.5以后出現的新特性:
①自動裝箱
如:Integer x = new Integer(5);自動裝箱后:Integer x = 5;//5相當于new Integer(5)。
x = x + 2;//首先對x進行了自動拆箱,轉成int后參與運算,再自動裝箱賦給x。
②Integer m = 128;Integer n = 128;
Integer a = 127;Integer b = 127; System.out.println(m==n);//false System.out.println(a==b);//true.因為a和b指向了同一個Integer對象。因為當數值在byte范圍內時,對于新特性,如果該數值已經存在,則不會再開辟新的空間。
Collection接口
–List接口
–Set接口
List:
凡是可以操作角標的方法都是該體系特有的方法。
List集合特有的迭代器——ListIterator,是Iterator的子接口。
在迭代時,不可以通過集合對象的方法操作集合中的元素,會發生ConcurrentModificationException異常,屬于線程安全問題。所以,在迭代時,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能對元素進行判斷、取出、刪除的操作,如果想要其他的操作如:添加,修改等,就需要使用其子接口——ListIterator.該接口只能通過List集合的ListIterator方法獲取。
List
–ArrayList:底層的數據結構使用數組結構。
–LinkedList:底層使用鏈表數據結構。
–Vector:底層是數組數據結構。線程同步。已被ArrayList替代。
ArrayList特點:查詢速度快。但是增刪稍慢。線程不同步。
LinkedList特點:增刪速度很快,查詢稍慢。
枚舉就是Vector特有的取出方式。其實枚舉和迭代器是一樣的。因為枚舉的名稱以及方法的名稱都過長,所以被迭代器取代了。
LinkedList特有方法:
addFirst();
addLast();
getFirst();
getLast();
獲取元素,但不刪除元素。如果集合中沒有元素,會出現NoSuchElementException
removeFirst();
removeLast();
獲取元素,但是元素被刪除。如果集合中沒有元素,會出現NoSuchElementException
JDK1.6出現了替代方法:
offerFirst();
offerLast();
添加元素
peekFirst();
peekLast();
獲取元素,但不刪除元素。如果集合中沒有元素,會返回null。
pollFirst();
pollLast();
獲取元素,但是元素被刪除。如果集合中沒有元素,會返回null。
Set:
元素是無序的(存入和取出的順序不一定一致),元素不可以重復。其功能和Collection是一致的。Set的底層使用的是Map集合。
Set
–HashSet:底層數據結構是哈希表。
–TreeSet:可以對Set集合中的元素進行排序。底層數據結構是二叉樹。
HashSet 是如何保證元素唯一性的?
是通過元素的兩個方法,hashCode和equals來完成。如果元素的HashCode值相同,才會判斷equals是否為true。如果元素的hashCode值不同,不會調用equals()。
注意:對于判斷元素是否存在,以及刪除等操作,依賴的方法是元素的hashCode和equals方法。
TreeSet保證元素唯一性的依據:
compareTo()方法return 0.
TreeSet排序的第一種方式:
讓元素自身具備比較性。元素需要實現Comparable接口,覆蓋compareTo()方法。這種方式也稱為元素的自然順序,或者叫做默認順序。
TreeSet排序的第二種方式:
當元素自身不具備比較性時,或者具備的比較性不是所需要的。這時就需要讓集合自身具備比較性。在集合初始化時,就有了比較方式。
JDK1.5版本以后出現的新特性。用于解決安全問題,是一個類型安全機制。
基本術語:以ArrayList為例:<>念著typeof
ArrayList中的E稱為類型參數變量。
ArrayList中的Integer稱為實際類型參數。
整個稱為ArrayList泛型類型。
整個ArrayList稱為參數化的類型ParameterizedType。
好處:
①將運行時期出現的問題ClassCastException,轉移到了編譯時期。方便于程序員解決問題。讓運行事情問題減少,安全。②避免了強制類型轉換的麻煩。
格式:
通過<>來定義要操作的引用數據類型。
在使用java提供的對象時,什么時候寫泛型呢?
通常在集合框架中很常見,只要見到<>就要定義泛型。其實<>就是用來接受類型的。當使用集合時,將集合中要存儲的數據類型作為參數傳遞到<>中即可。
什么時候定義泛型類?
當類中要操作的引用數據類型不確定的時候,早期定義Object類完成擴展。現在定義泛型來完成擴展。
泛型定義在方法上:
泛型類定義的泛型,在整個類中有效。如果被方法使用,那么泛型類的對象明確要操作的具體類型后,所有要操作的類型就已經固定了。為了讓不同方法可以操作不同類型,而且類型還不確定。那么可以將泛型定義在方法上。
靜態方法不能使用類定義的泛型。而應單獨定義泛型。
泛型的高級應用:
? 通配符。也可以理解為占位符。
泛型的限定:
? extends E:可以接受E類型或者E的子類型。上限。
? super E:可以接受E類型或者E的父類型。下限。
注意事項:
使用泛型時,泛型類型須為引用類型,不能是基本數據類型。
兩邊都有泛型限定時,須一致。
一邊有泛型限定,一邊沒有是正確的泛型。
–Hashtable:底層是哈希表數據結構,不可以存入null鍵null值。該集合是線程同步。jdk1.0出現,效率低。
–HashMap:底層是哈希表數據結構,允許使用null值和null鍵,該集合是不同步的。將hashtable替代,jdk1.2出現,效率高。
–TreeMap:底層是二叉樹數據結構。線程不同步。可以用于給map集合中的鍵進行排序。
Map集合:該集合存儲鍵值對。一對一對往里存。而且要保證鍵的唯一性。
①添加
put(K key, V value) 將指定的值與此映射中的指定鍵關聯(可選操作)。
putAll(Map m) 從指定映射中將所有映射關系復制到此映射中(可選操作)。
②刪除
clear() 從此映射中移除所有映射關系(可選操作)。
remove(Object key) 如果存在一個鍵的映射關系,則將其從此映射中移除(可選操作)。
③判斷
isEmpty() 如果此映射未包含鍵-值映射關系,則返回 true。
containsKey(Object key) 如果此映射包含指定鍵的映射關系,則返回 true。
containsValue(Object value) 如果此映射將一個或多個鍵映射到指定值,則返回 true。
④獲取
get(Object key) 返回指定鍵所映射的值;如果此映射不包含該鍵的映射關系,則返回 null。
size() 返回此映射中的鍵-值映射關系數。
values() 返回此映射中包含的值的 Collection 視圖。
【重點】
entrySet() 返回此映射中包含的映射關系的 Set 視圖。
keySet() 返回此映射中包含的鍵的 Set 視圖。
Map集合的兩種取出方式:
Set> entrySet(): 將集合中的映射關系存入到了set集合中,而這個關系的數據類型就是:Map.Entry.
Set keySet(): 將map中所有的鍵值存入到Set集合。因為Set具備迭代器,所以可以用迭代方式取出所有的鍵,
再根據get()方法獲取每一個鍵對應的值。
Map集合的取出原理:
將map集合轉成set集合。再通過迭代器取出。
將集合轉成數組
指定類型的數組的長度的定義:
當指定類型的數組長度少于了集合的size(),那么該方法內部會創建一個新的數組,長度為集合的size();當指定類型的數組長度大于了集合的size(),就不會創建新數組,而是使用傳遞進來的數組.所以創建一個剛剛好的數組最優.
為什么要將集合變數組?
為了限定對元素的操作。不需要進行增刪了。
只適用于數組和實現Iterator的集合。只能遍歷,不能對數據進行修改。
格式:
for(數據類型 變量名 : 被遍歷的集合(Collection)或者數組){ }
對集合進行遍歷,只能獲取集合元素,不能對集合進行操作。迭代器除了遍歷,還可以進行remove集合中元素的動作。如果使用ListIterator,還可以在遍歷過程中對集合進行增刪改查的動作。
傳統for和高級for的區別:
高級for有一個局限性,即必須有別遍歷的目標。
建議在遍歷數組的時候,用傳統for。因為傳統for可以定義角標。
其實就是數組參數的簡寫形式。不用每一次都手動的建立數組對象。只要將要操作的元素作為參數傳遞即可。隱式將這些參數封裝成了數組。
方法的可變參數,在使用時注意:可變參數一定要定義在參數列表最后面。
格式:
import static java.包名.類名.*;//導入的是某個類中的靜態成員.
例如:``import static java.util.Arrays.*;`
好處:
在程序中使用這個類中的靜態方法的時候就不要再去寫包名。
描述系統一些信息。
System: 靜態方法和靜態成員;
out:標準輸出,默認是控制臺;
in:標準輸入,默認是鍵盤。
獲取系統屬性信息:
Properties getProperties();
該類沒有提供構造函數。說明不可以new對象。該類提供了一個非靜態方法用來獲取本類對象,該方法是靜態的,并返回值類型是本類類型。
根據這個特點判斷,該類使用了單例設計模式。
該方法是:static Runtime getRuntime(){}
|-DateFormat:是日期/時間格式化子類的抽象類,它以與語言無關的方式格式化并解析日期或時間.
|-SimpleDateFormat:是一個以與語言環境有關的方式來格式化和解析日期的具體類.該類使得可以選擇任何用戶定義的日期-時間格式的模式.
抽象類,它為特定瞬間與一組諸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日歷字段之間的轉換提供了一些方法,并為操作日歷字段(例如獲得下星期的日期)提供了一些方法.
Calendar子類:
GregorianCalendar:
GregorianCalendar 是 Calendar 的一個具體子類,提供了世界上大多數國家/地區使用的標準日歷系統.
字節流和字符流
字節流兩個基類:
InputStreamOutputStream
字符流兩個基類:
ReaderWriter
緩沖區:
緩沖區的出現是為了提高流的操作效率。所以在創建緩沖區之前,必須要先有流對象。
BufferedWriter緩沖區提供了一個跨平臺的換行符,newLine()。
裝飾設計模式:
當想要對已有的對象進行功能增強時,可以定義類,將已有對象傳入,基于已有的功能,并提供加強功能。那么自定義的該類稱為裝飾類。
裝飾類通常會通過構造方法接受被裝飾的對象。并基于被裝飾的對象的功能,提供更強的功能。
裝飾設計模式和繼承的區別:
裝飾設計模式比繼承要靈活,避免了繼承體系的臃腫。而且降低了類與類之間的關系。裝飾類因為增強已有對象,具備的功能和已有的是相同的,只不過提供了更強的功能。所以裝飾類和別裝飾類通常是都屬于一個體系中的。
java.io.Reader
|-java.io.BufferedReader
|-java.io.LineNumberReader
LineNumberReader: 跟蹤行號的緩沖字符輸入流。此類定義了方法setLineNumber(int)和getLineNumber(),它們可分別用于設置和獲取當前行號。默認情況下,行編號從0開始。
流操作規律之一:
1,明確源和目的。
源:輸入流。InputStream Reader
目的:輸出流。OutputStream Writer
2,操作的數據是否是純文本。
是,字符流。
不是,字節流。
3,當體系明確后,再明確要使用哪個具體的對象。
通過設備來進行區分:
源設備:內存,硬盤,鍵盤。
目的設備:內存,硬盤,控制臺。
1,需求:講一個文本文件中數據存儲到另一個文件中。復制文件。
源:因為是源,所以使用讀取流。InputStream Reader
是不是操作文本文件:
是:選擇Reader.
明確要使用該體系中的哪個對象?
明確設備:硬盤。
Reader體系中可以操縱文件的對象是 FileReader
是否需要提高效率:是!加入Reader體系中緩沖區BufferedReader.
FileReader fr = new FileReader(“a.txt”);
BufferedReader bufr = new BufferedReader(fr);
目的:OutputStream Writer
是否是純文本:是!Writer.
設備:硬盤,一個文件。
Writer體系中可以操作文件的對象FileWriter.
是否需要提高效率:是!加入Writer體系中緩沖區 BufferedWriter.
FileWriter fw = new FileWriter(“b.txt”);
BufferedWriter bufr = new BufferedWriter(fw);
流操作規律之二:
2,需求:將鍵盤錄入的數據保存到一個文件中。這個需求中有源和目的都存在。那么分別分析:源:InputStream Reader. 是不是純文本?是!Reader.
設備:鍵盤。對應的對象是System.in.
可是System.in對應的是字節流,為了操作鍵盤的文本數據方便。轉成字符流按照字符串操作最方便。所以既然明確了Reader,那么就將System.in轉換成Reader.用Reader體系中的轉換流,InputStreamReader.
InputStreamReader isr = new InputStream(System.in);
需要提高效率?需要!BufferedReader
BufferedReader bufr = new BufferedReader(isr);
File的常見操作1:
創建
boolean createNewFile(): 在指定位置創建文件,如果該文件已經存在,則不創建,返回false。
和輸出流不一樣,輸出流對象一建立創建文件,而且文件已經存在,會覆蓋。
刪除
boolean delete():刪除失敗返回false。
void deleteOnExit():在程序退出時刪除指定文件。
判斷
boolean exists():
boolean isFile():
boolean isDirectory():
boolean isHidden():
boolean isAbsolute(): 測試此抽象路徑名是否為絕對路徑名.
獲取信息
String getName(): 返回由此抽象路徑名表示的文件或目錄的名稱.
String getPath(): 將此抽象路徑名轉換為一個路徑名字符串.
String getParent(): 返回此抽象路徑名父目錄的路徑名字符串;如果此路徑名沒有指定父目錄,則返回 null.
String getAbsolutePath(): 返回此抽象路徑名的絕對路徑名字符串.
long lastModified(): 返回此抽象路徑名表示的文件最后一次被修改的時間.
long length(): 返回由此抽象路徑名表示的文件的長度.
File常見操作2
String[] list() 返回一個字符串數組,這些字符串指定此抽象路徑名表示的目錄中的文件和目錄 .
String[] list(FilenameFilter filter) 返回一個字符串數組,這些字符串指定此抽象路徑名表示的目錄中滿足指定過濾器的文件和目錄 .
File[] listFiles() 返回一個抽象路徑名數組,這些路徑名表示此抽象路徑名表示的目錄中的文件 .
static File[] listRoots() 列出可用的文件系統根 .
long length() 返回由此抽象路徑名表示的文件的長度 .
public interface FilenameFilter 實現此接口的類實例可用于過濾器文件名.
此接口中只有一個方法:boolean accept(File dir, String name) 測試指定文件是否應該包含在某一文件列表中 .
遞歸:
因為目錄中還有目錄,只要使用同一個列出目錄功能的函數完成即可。在列出過程中出現的還是目錄的話,還可以再次調用本功能。也就是函數自身調用自身。
這種表現形式,或者編程手法,稱為遞歸.
遞歸要注意:
限定條件
遞歸的次數,盡量避免內存溢出。
Properties
Properties是Hashtable的子類。
Properties 可保存在流中或從流中加載。屬性列表中每個鍵及其對應值都是一個字符串。也就是說它具備map集合的特點。而且它里面存儲的鍵值對都是字符串。該類是集合中和IO技術相結合的集合容器。
該對象的特點:
可以用于鍵值對形式的配置文件。
字節打印流:PrintStream
構造函數可以接收的參數類型:
1,file對象,File
2,字符串路徑。String
3,字節輸出流。OutputStream
字符打印流:PrintWriter
構造函數可以接收的參數類型:
1,file對象。File
2,字符串路徑。String
3,字節輸出流。OutputStream
4,字符輸出流,Writer.
SequenceInputStream:
表示其他輸入流的邏輯串聯。它從輸入流的有序集合開始,并從第一個輸入流開始讀取,直到到達文件末尾,接著從第二個輸入流讀取,依次類推,直到到達包含的最后一個輸入流的文件末尾為止。
ObjectOutputStream: 將 Java 對象的基本數據類型和圖形寫入 OutputStream。可以使用 ObjectInputStream 讀取(重構)對象。
通過在流中使用文件可以實現對象的持久存儲。如果流是網絡套接字流,則可以在另一臺主機上或另一個進程中重構對象。
只能將支持 java.io.Serializable 接口的對象寫入流中。
ObjectInputStream: 對以前使用 ObjectOutputStream 寫入的基本數據和對象進行反序列化。
ObjectInputStream 用于恢復那些以前序列化的對象。
ObjectOutputStream 和 ObjectInputStream 分別與 FileOutputStream 和 FileInputStream 一起使用時,
可以為應用程序提供對對象圖形的持久存儲。
Serializable 接口:
類通過實現 java.io.Serializable 接口以啟用其序列化功能。序列化接口沒有方法或字段,僅用于標識可序列化的語義。
PipedOutputStream:
可以將管道輸出流連接到管道輸入流來創建通信管道。管道輸出流是管道的發送端。通常,數據由某個線程寫入 PipedOutputStream 對象,并由其他線程從連接的 PipedInputStream 讀取。不建議對這兩個對象嘗試使用單個線程,因為這樣可能會造成該線程死鎖。
PipedInputStream:
管道輸入流應該連接到管道輸出流;管道輸入流提供要寫入管道輸出流的所有數據字節。通常,數據由某個線程從 PipedInputStream 對象讀取,并由其他線程將其寫入到相應的 PipedOutputStream。不建議對這兩個對象嘗試使用單個線程,因為這樣可能死鎖線程。
管道輸入流包含一個緩沖區,可在緩沖區限定的范圍內將讀操作和寫操作分離開。如果向連接管道輸出流提供數據字節的線程不再存在,則認為該管道已損壞。
該類不算是IO體系中的子類。而是直接繼承自Object。但是它是IO包中的成員,因為它具備讀和寫功能。內部封裝了一個數組,而且通過指針對數組的元素進行操作。可以通過getFileRointer獲取指針位置,同時,可以通過seek改變指針的位置。
其實,完成讀寫的原理就是內部封裝了字節數如流和字節輸出流。
該類只能操作文件。而且有模式:只讀r,讀寫rw等。
該對象的構造函數要操作的文件不存在,會自動創建。
如果模式為只讀,不會創建文件。會去讀取一個已存在文件,如果該文件不存在,則會出現異常。如果模式為rw,如果文件不存在會自動創建,如果存在則不會覆蓋。
DataInputStream:
數據輸入流允許應用程序以與機器無關方式從底層輸入流中讀取基本 Java 數據類型。應用程序可以使用數據輸出流寫入稍后由數據輸入流讀取的數據。
DataInputStream 對于多線程訪問不一定是安全的。 線程安全是可選的,它由此類方法的使用者負責。
DataOutputStream:
數據輸出流允許應用程序以適當方式將基本 Java 數據類型寫入輸出流中。然后,應用程序可以使用數據輸入流將數據讀入。
void writeUTF(String str): 以與機器無關方式使用 UTF-8 修改版編碼將一個字符串寫入基礎輸出流 .
ByteArrayInputStream:
包含一個內部緩沖區,該緩沖區包含從流中讀取的字節。內部計數器跟蹤 read 方法要提供的下一個字節。 關閉 ByteArrayInputStream 無效。
此類中的方法在關閉此流后仍可被調用,而不會產生任何 IOException。
ByteArrayOutputStream:
此類實現了一個輸出流,其中的數據被寫入一個 byte 數組。緩沖區會隨著數據的不斷寫入而自動增長。可使用 toByteArray() 和 toString() 獲取數據。
關閉 ByteArrayOutputStream 無效。此類中的方法在關閉此流后仍可被調用,而不會產生任何 IOException。
void writeTo(OutputStream out):
將此 byte 數組輸出流的全部內容寫入到指定的輸出流參數中,這與使用 out.write(buf, 0, count) 調用該輸出流的 write 方法效果一樣。
ByteArrayInputStream:在構造時,需要接受數據源。而且數據源是一個字節數組。
ByteArrayOutputStream:在構造時,不用定義數據目的,因為該對象中已經內部封裝了可變長度的字節數組。也就是數據目的地。
因為這兩個流對象都操作的數組,并沒有使用系統資源。所以,不用進行close關閉。
**字符類 **
[abc] a、b 或 c(簡單類)
[^abc] 任何字符,除了 a、b 或 c(否定)
[a-zA-Z] a 到 z 或 A 到 Z,兩頭的字母包括在內(范圍)
[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集)
[a-z&&[def]] d、e 或 f(交集)
[a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](減去)
[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](減去)
**預定義字符類 **
. 任何字符(與行結束符可能匹配也可能不匹配)
\d 數字:[0-9]
\D 非數字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 單詞字符:[a-zA-Z_0-9]
\W 非單詞字符:[^\w]
Greedy 數量詞
X? X,一次或一次也沒有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超過 m 次
知識點:
1,匹配:matches();
2,切割:split();
3,替換: replaceAll();
4,獲取。
public class RegularTest1 { // 匹配:電話號碼匹配:13xxx,18xxx,15xxx.11位. public static void checkTel() { String tel = "13893476555"; String regular = "[1][135]\\d{9}"; System.out.println(tel.matches(regular)); }
// 切割:
public static void splitTest(String str, String regu) { String[] arr = str.split(regu); for (String s : arr) { System.out.println(s); } }
// 替換
public static void replaceAllTest(String str, String regu, String newStr){ String str1 = str.replaceAll(regu, newStr); System.out.println(str1); } public static void main(String[] args) { // checkTel(); // 按照逗號切割 // splitTest("java,android,ios", ","); // 按照.切割(注意轉義) // splitTest("java.android.ios", "\\."); // 按照空格切割. X+ X,一次或多次 . //splitTest("java android ios", " +"); // 切割地址(特殊) // splitTest("d:\\shuduapp\\AndroidManifest.xml", "\\\\"); /*按照疊詞完成切割。為了可以讓規則的結果被重用,可以將規則封成一個組。用()完成。組的出現都有編號。從1開始。 想要使用已有的組可以通過\n(n就是組的編號)的形式來獲取。*/ // 疊詞切割 : 疊詞只有兩個相同的字母 // splitTest("asddcdjefkksdfccsdfas", "(.)\\1"); // 疊詞切割 : 疊詞有多個相同的字母 //splitTest("asddddcdjefkkkksdfcccccccccsdfas", "(.)\\1+"); // 將字符串中的數字替換成# //replaceAllTest("asdf5465189sdfwe2s64gq6re5h11df315", "\\d+", "#"); // 將字符串中連續3個以上的數字替換成# //replaceAllTest("asdf5465189sdfwe2s64gq6re5h11df315", "\\d{3,}", "#"); // 將疊詞替換成&. replaceAllTest("asddcdjefkksdfccccsdfas", "(.)\\1+", "&"); // 將重疊的字母替換成單個字母. replaceAllTest("asddcdjefkksdfccccsdfas", "(.)\\1+", "$1"); // $1是獲取前面的組. }
獲取
步驟:
1,將正則表達式封裝成對象。
2,讓正則對象和要操作的字符串相關聯。
3,關聯后,獲取正則匹配引擎。
4,通過引擎對符合規則的子串進行操作,比如取出。
邊界匹配器
^ 行的開頭
$ 行的結尾
\b 單詞邊界
\B 非單詞邊界
\A 輸入的開頭
\G 上一個匹配的結尾
\Z 輸入的結尾,僅用于最后的結束符(如果有的話)
\z 輸入的結尾
public final class Pattern : 正則表達式的編譯表示形式。
指定為字符串的正則表達式必須首先被編譯為此類的實例。然后,可將得到的模式用于創建 Matcher 對象,依照正則表達式,該對象可以與任意字符序列匹配。執行匹配所涉及的所有狀態都駐留在匹配器中,所以多個匹配器可以共享同一模式。
public final class Matcher:通過解釋 Pattern 對 character sequence 執行匹配操作的引擎。
boolean find(): 嘗試查找與該模式匹配的輸入序列的下一個子序列。
String group(): 返回由以前匹配操作所匹配的輸入子序列。
public class RegularTest2 { public static void getTest(){ String str = "ming tian shi zhou wu, jin tian zhou si le."; System.out.println(str); // 取出str中的由4個字母組成的單詞. String regu = "\\b[a-z]{4}\\b"; // 1,將正則表達式封裝成對象。 Pattern p = Pattern.compile(regu); // 2,讓正則對象和要操作的字符串相關聯。 Matcher m = p.matcher(str); while(m.find()){ System.out.println(m.group()); System.out.println(m.start()+"============"+m.end()); } } public static void main(String[] args) { getTest(); } }
枚舉類也是一種特殊形式的java類。
枚舉類中聲明的每一個枚舉值代表枚舉類的一個實例對象。
與java中的普通類一樣,在聲明枚舉類時,也可以聲明屬性、方法和構造函數,但枚舉類的構造函數必須為私有的。
枚舉類也可以實現接口、或繼承抽象類。
JDK5中擴展了switch語句,它除了可以接受int,byte,char,short外,還可以接受一個枚舉類型。
若枚舉類只有一個枚舉值,則可以當作單態設計模式使用。
常用方法:
String name():
返回此枚舉常量的名稱,在其枚舉聲明中對其進行聲明。
int ordinal():
返回枚舉常量的序數(它在枚舉聲明中的位置,其中初始常量序數為零)。
static > T valueOf(Class enumType, String name):
返回帶指定名稱的指定枚舉類型的枚舉常量
【注意】
values(): 此方法雖然在JDK文檔中查找不到,但每個枚舉類都具有該方法,它用于遍歷枚舉的所有枚舉值。
加載類的三種方式
public void loadClass() throws Exception { // 加載類的第一種方式 Class clazz1 = Class.forName("Person"); // 加載類的第二種方式 Class calzz2 = Person.class; // 加載類的第三種方式 Class clazz3 = new Person().getClass(); }
反射類的字段
常用方法:
Object get(Object obj): 返回指定對象上此 Field 表示的字段的值 .
void set(Object obj, Object value): 將指定對象變量上此 Field 對象表示的字段設置為指定的新值 .
Class getType(): 返回一個 Class 對象,它標識了此 Field 對象所表示字段的聲明類型.
反射方法:
反射構造方法
@Test public void reflectConstruct() throws Exception { Class clazz1 = Class.forName("Person"); Constructor c1 = clazz1.getConstructor(null); // 這里的參數是可變參數,此時反射的是無參的,所以是Null. Person p1 = (Person) c1.newInstance(null); // 同上 System.out.println(); Constructor c2 = clazz1.getConstructor(java.lang.String.class); Person p2 = (Person) c2.newInstance("constructor2"); System.out.println(); Constructor c3 = clazz1.getConstructor(java.lang.String.class, int.class); Person p3 = (Person) c3.newInstance("constructor3",03); System.out.println(); // 訪問私有構造函數 Constructor c4 = clazz1.getDeclaredConstructor(java.util.List.class); c4.setAccessible(true); // 暴力反射.打開私有權限. Person p4 = (Person) c4.newInstance(new ArrayList()); System.out.println(); // 創建對象的另外一種途徑 Person p5 = (Person) clazz1.newInstance(); // 底層調用的是反射類的無參構造函數.若反射類沒有無參構造函數則會報錯. System.out.println(p5); }
反射主方法(兩種處理方式):public static void main(String[] args)
Method m6 = clazz.getMethod("main", String[].class); //m6.invoke(null, new Object[]{new String[]{"11","22"}}); m6.invoke(null, (Object)new String[]{"44","55"});
使用內省API操作bean的屬性
static BeanInfo getBeanInfo(Class beanClass): 在 Java Bean 上進行內省,了解其所有屬性、公開的方法和事件。
static BeanInfo getBeanInfo(Class beanClass, Class stopClass):在給定的“斷”點之下,在 Java Bean 上進行內省,了解其所有屬性和公開的方法。
static BeanInfo getBeanInfo(Class beanClass, int flags):在 Java Bean 上進行內省,了解其所有屬性、公開的方法和事件,并將結果用一些控制標記表示。
PropertyDescriptor[] getPropertyDescriptors():獲得 beans PropertyDescriptor。
大家好,我是一名正在學習Java的程序員,功夫不負有心人,每天保持學習,掌握一項技能其實用不了多長時間,加油!
Java 任務調度 面向對象編程
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。