JDK1.5新特性: 1.自動(dòng)拆裝箱. 2.泛型 3.可變參數(shù) 4.靜態(tài)導(dǎo)入 5.增強(qiáng)for循環(huán) 6.互斥鎖 7.枚舉 8.注解 JDK1.6新特性: 1.Desktop類和SystemTray類 2.使用JAXB2來實(shí)現(xiàn)對(duì)象與XML之間的映射 3.StAX 4.使用Compiler API 5.輕量級(jí)Http Server API 6.插入式注解處理API(Pluggable Annotation Processing API) 7.用Console開發(fā)控制臺(tái)程序 8.對(duì)腳本語言的支持 9.Common Annotations
JDK1.7新特性: 1 對(duì)集合類的語言支持; 2 自動(dòng)資源管理; 3 改進(jìn)的通用實(shí)例創(chuàng)建類型推斷; 4 數(shù)字字面量下劃線支持; 5 switch中使用string; 6 二進(jìn)制字面量0b001; 7 簡(jiǎn)化可變參數(shù)方法調(diào)用。 8 泛型簡(jiǎn)化,出現(xiàn)菱形泛型 9 異常的多個(gè)catch合并,每個(gè)異常用或| 10 try-with-resources 語句
JDK1.8 新特性: 一、接口的默認(rèn)方法:Java 8允許我們給接口添加一個(gè)非抽象的方法實(shí)現(xiàn),只需要使用 default關(guān)鍵字即可,這個(gè)特征又叫做擴(kuò)展方法, 二、Lambda 表達(dá)式:Collections.sort(names, (a, b) -> b.compareTo(a));Java編譯器可以自動(dòng)推導(dǎo)出參數(shù)類型,所以你可以不用再寫一次類型。 三、函數(shù)式接口:每一個(gè)lambda表達(dá)式都對(duì)應(yīng)一個(gè)類型,通常是接口類型。而“函數(shù)式接口”是指僅僅只包含一個(gè)抽象方法的接口,每一個(gè)該類型的lambda表達(dá)式都會(huì)被匹配到這個(gè)抽象方法。 因?yàn)?默認(rèn)方法 不算抽象方法,所以你也可以給你的函數(shù)式接口添加默認(rèn)方法。 四、方法與構(gòu)造函數(shù)引用:Java 8 允許你使用 :: 關(guān)鍵字來傳遞方法或者構(gòu)造函數(shù)引用,上面的代碼展示了如何引用一個(gè)靜態(tài)方法,我們也可以引用一個(gè)對(duì)象的方法: 五、Lambda 作用域:在lambda表達(dá)式中訪問外層作用域和老版本的匿名對(duì)象中的方式很相似。你可以直接訪問標(biāo)記了final的外層局部變量,或者實(shí)例的字段以及靜態(tài)變量。 六、訪問局部變量:lambda表達(dá)式中訪問外層的局部變量 七、訪問對(duì)象字段與靜態(tài)變量:lambda內(nèi)部對(duì)于實(shí)例的字段以及靜態(tài)變量是即可讀又可寫。該行為和匿名對(duì)象是一致的: 八、訪問接口的默認(rèn)方法:Lambda表達(dá)式中是無法訪問到默認(rèn)方法的 九、Date API:Java 8 在包java.time下包含了一組全新的時(shí)間日期API。新的日期API和開源的Joda-Time庫差不多,但又不完全一樣 十、Annotation 注解:在Java 8中支持多重注解了,Java 8允許我們把同一個(gè)類型的注解使用多次,只需要給該注解標(biāo)注一下@Repeatable即可,
斷言的使用方式: 斷言是一種測(cè)試和調(diào)測(cè)階段所使用的戰(zhàn)術(shù)工具. 斷言的初衷:在一個(gè)具有自我保護(hù)能力的程序中,斷言很常用.假設(shè)確信某個(gè)屬性符合要求,并且代碼的執(zhí)行依賴于這個(gè)屬性.例如,需要計(jì)算 double y = Math.sqrt(x); 我們確信,這里的x是一個(gè)非負(fù)數(shù)的值.原因是:是另外一個(gè)計(jì)算的結(jié)果,而這個(gè)結(jié)果不可能是負(fù)值;或者x是一個(gè)方法的參數(shù),而這個(gè)方法要求它的調(diào)用者只能提供一個(gè)正整數(shù). 然而,還是希望進(jìn)行檢查,以避免讓"不是一個(gè)數(shù)"的數(shù)值參與計(jì)算操作.當(dāng)然,也可以拋出一個(gè)異常: if(x<0) throw new IllegalArgumentException("x<0"); 但是需要注意的是,這段代碼會(huì)一直保留在程序中,即使測(cè)試完畢也不會(huì)自動(dòng)的刪除.如果在程序中包含有大量的這種檢查,程序運(yùn)行起來會(huì)相當(dāng)慢. 斷言機(jī)制允許在測(cè)試期間向代碼中插入一些檢查語句.當(dāng)代碼發(fā)布時(shí),這些插入的檢查語句將會(huì)被自動(dòng)的移走.
開啟斷言:2.在myEclipse中,Windows -> Preferences ->Java ->Installed JREs ->點(diǎn)擊正使用的JDK ->Edit ->Default VM Arguments文本框中輸入:-ea或者-enableassertions 斷言的格式: java中語音引入關(guān)鍵字assert.這個(gè)關(guān)鍵字有兩種表現(xiàn)形式: 1.assert 條件: 例如:assert x>=0; 想要斷言x是一個(gè)非負(fù)數(shù)值,只需要簡(jiǎn)單的使用這條語句. 2.assert 條件:表達(dá)式;例如:assert x>=0 : x; 或者將x的實(shí)際值傳遞給AssertionError對(duì)象,從而可以在后面顯示出來. 這兩個(gè)格式都會(huì)對(duì)條件進(jìn)行檢測(cè),如果結(jié)果為false,則拋出一個(gè)AssertionError異常. 在第二種格式中,表達(dá)式將被傳入AssertionEeror的構(gòu)造器,并轉(zhuǎn)換成一個(gè)消息字符串. 注釋:"表達(dá)式"部分的唯一目的是產(chǎn)生一個(gè)消息字符串.AssertionErro對(duì)象并不存儲(chǔ)表達(dá)式的值,因此,不可能在以后得到它.正如JDK文檔所描述的那樣:如果使用表達(dá)式的值, 就會(huì)鼓勵(lì)程序員試圖從斷言中恢復(fù)程序的運(yùn)行,這不符合斷言機(jī)制的初衷.
啟用和禁用斷言
在默認(rèn)情況下,斷言是被禁用的??梢栽诔绦蜻\(yùn)行時(shí)用-enableassertions或-ea選項(xiàng)啟用它: java -enableassertions MyApp 啟用或者禁用斷言不必重新編譯程序。啟動(dòng)或者禁用斷言是類加載器的功能。當(dāng)斷言被禁用時(shí),類加載器將跳過斷言代碼,因此,不會(huì)降低程序的運(yùn)行速度。 也可以在某個(gè)類或者某個(gè)包中使用斷言,例如: java -ea:MyClass -ea:com.mycompany.mylib... MyApp 這條命令將開啟MyClass類以及在com.mycompany.mylib包和它的子包中的所有類的斷言。選項(xiàng)-ea將開啟默認(rèn)包中的所有類的斷言。 也可以使用-disableassertions或-da禁用某個(gè)特定的類和包的斷言: java -ea:... -da:MyClass MyApp 有些類不是由類加載器加載,而是直接由虛擬機(jī)加載。可以使用這些開關(guān)有選擇地啟用或禁用哪些類中的斷言。 然而,啟用和禁用所有斷言的-ea和-da開關(guān)并不能應(yīng)用到那些沒有類加載器的“系統(tǒng)類”上。對(duì)于這些系統(tǒng)類而言,需要使用-enablesystemassertions/-esa開關(guān)啟動(dòng)斷言。 使用斷言完成參數(shù)檢查
API:java.long.ClassLoader 1.0 子類MLet void setDefaultAssertionStatus(Boolean b) //1.4 對(duì)于通過類加載器加載的所有類來說,如果沒有顯示的說明類或者包的斷言 狀態(tài),就啟用或禁用斷言. void setClassAssertionSatus(String className,boolean b) //1.4 對(duì)于給定的類和它的內(nèi)部類,啟用或禁用斷言. void setPackageAssertionStatus(String packageName,boolean b) //1.4 對(duì)于給定包和其子包中的所有類,啟用或禁用斷言. void clearAssertionStatus() //1.4 移去所有類和包的顯示斷言狀態(tài)設(shè)置,并禁用所有通過這個(gè)類加載器加載的類的斷言.
java中的3中處理系統(tǒng)錯(cuò)誤的機(jī)制: 拋出一個(gè)異常 日志 使用斷言 什么時(shí)候應(yīng)該使用斷言呢? 斷言失敗是致命的、不可恢復(fù)的錯(cuò)誤 斷言檢查只用于開發(fā)和測(cè)試階段 因此,不應(yīng)該使用斷言向程序的其他部分通告發(fā)生了可恢復(fù)性的錯(cuò)誤,或者,不應(yīng)該作為程序向用戶通告問題的手段。斷言只應(yīng)該是在測(cè)試階段確定程序內(nèi)部錯(cuò)誤的位置。 斷言是一種測(cè)試和調(diào)試階段所使用的戰(zhàn)術(shù)性工具;而日志記錄是一種在程序的整個(gè)生命周期都可以使用的策略性工具。 public class App { public static void main( String[] args ) { int a = -1; assert a > 0 : "liuni是笨蛋"; System.out.println( "Hello World!" ); } }
程序中記錄日志一般有兩個(gè)目的:Troubleshooting和顯示程序運(yùn)行狀態(tài)。好的日志記錄方式可以提供我們足夠多定位問題的依據(jù)。日志記錄大家都會(huì)認(rèn)為簡(jiǎn)單,但如何通過日志可以高效定位問題并不是簡(jiǎn)單的事情。這里列舉下面三個(gè)方面的內(nèi)容,輔以代碼示例,總結(jié)如何寫好日志,希望對(duì)他人有所啟發(fā)和幫助:
怎樣記日志可以方便Troubleshooting 程序運(yùn)行狀態(tài)可以記哪些 應(yīng)該避免怎樣的日志方式 怎樣記日志可以方便Troubleshooting? 1. 對(duì)外部的調(diào)用封裝
程序中對(duì)外部系統(tǒng)與模塊的依賴調(diào)用前后都記下日志,方便接口調(diào)試。出問題時(shí)也可以很快理清是哪塊的問題
[java] view plain copy LOG.debug("Calling external system:" + parameters); Object result = null; try { result = callRemoteSystem(params); LOG.debug("Called successfully. result is " + result); } catch (Exception e) { LOG.warn("Failed at calling xxx system . exception : " + e); }
2.狀態(tài)變化
程序中重要的狀態(tài)信息的變化應(yīng)該記錄下來,方便查問題時(shí)還原現(xiàn)場(chǎng),推斷程序運(yùn)行過程
[java] view plain copy boolean isRunning; isRunning = true; LOG.info("System is running"); //... isRunning = false; LOG.info("System was interrupted by " + Thread.currentThread().getName());
3.系統(tǒng)入口與出口:
這個(gè)粒度可以是重要方法級(jí)或模塊級(jí)。記錄它的輸入與輸出,方便定位
[java] view plain copy void execute(Object input) { LOG.debug("Invoke parames : " + input); Object result = null; //business logic LOG.debug("Method result : " + result); }
4.業(yè)務(wù)異常:
任何業(yè)務(wù)異常都應(yīng)該記下來:
[java] view plain copy try { //business logical } catch (IOException e) { LOG.warn("Description xxx" , e); } catch (BusinessException e) { LOG.warn("Let me know anything"); } catch (Exception e) { LOG.error("Description xxx", e); }
5.非預(yù)期執(zhí)行:
為程序在“有可能”執(zhí)行到的地方打印日志。如果我想刪除一個(gè)文件,結(jié)果返回成功。但事實(shí)上,那個(gè)文件在你想刪除之前就不存在了。最終結(jié)果是一致的,但程序得讓我們知道這種情況,要查清為什么文件在刪除之前就已經(jīng)不存在
[java] view plain copy int myValue = xxxx; int absResult = Math.abs(myValue); if (absResult < 0) { LOG.info("Original int " + myValue + "has nagetive abs " + absResult); }
6.很少出現(xiàn)的else情況:
else可能吞掉你的請(qǐng)求,或是賦予難以理解的最終結(jié)果
[java] view plain copy Object result = null; if (running) { result = xxx; } else { result = yyy; LOG.debug("System does not running, we change the final result"); }
日志記錄:
程序運(yùn)行狀態(tài)可以記哪些? 程序在運(yùn)行時(shí)就像一個(gè)機(jī)器人,我們可以從它的日志看出它正在做什么,是不是按預(yù)期的設(shè)計(jì)在做,所以這些正常的運(yùn)行狀態(tài)是要有的。
1. 程序運(yùn)行時(shí)間:
[java] view plain copy long startTime = System.currentTime(); // business logical LOG.info("execution cost : " + (System.currentTime() - startTime) + "ms");
2. 大批量數(shù)據(jù)的執(zhí)行進(jìn)度:
[java] view plain copy LOG.debug("current progress: " + (currentPos * 100 / totalAmount) + "%");
3.關(guān)鍵變量及正在做哪些重要的事情:
執(zhí)行關(guān)鍵的邏輯,做IO操作等等
[java] view plain copy String getJVMPid() { String pid = ""; // Obtains JVM process ID LOG.info("JVM pid is " + pid); return pid; } void invokeRemoteMethod(Object params) { LOG.info("Calling remote method : " + params); //Calling remote server }
應(yīng)該避免怎樣的日志方式? 1. 混淆信息的Log
日志應(yīng)該是清晰準(zhǔn)確的: 當(dāng)看到日志的時(shí)候,你知道是因?yàn)檫B接池取不到連接導(dǎo)致的問題么?
[java] view plain copy Connection connection = ConnectionFactory.getConnection(); if (connection == null) { LOG.warn("System initialized unsuccessfully"); }
2. 記錯(cuò)位置
產(chǎn)品代碼中,使用console記錄日志,導(dǎo)致沒有找到日志。
[java] view plain copy } catch (ConfigurationException e) { e.printStackTrace(); }
3. 記錯(cuò)級(jí)別
記錯(cuò)級(jí)別常常發(fā)生,常見的如:混淆代碼錯(cuò)誤和用戶錯(cuò)誤,如登錄系統(tǒng)中,如果惡意登錄,那系統(tǒng)內(nèi)部會(huì)出現(xiàn)太多WARN,從而讓管理員誤以為是代碼錯(cuò)誤??梢苑答佊脩粢藻e(cuò)誤,但是不要記錄用戶錯(cuò)誤的行為,除非想達(dá)到控制的目的。
[java] view plain copy LOG.warn("Failed to login by "+username+");
4. 遺漏信息
這里可能包含兩種情況:(1)用戶自己少寫了信息,導(dǎo)致毫無參考價(jià)值;(2)用戶調(diào)用log的方式導(dǎo)致丟失信息,如下例,沒有stack trace.
[java] view plain copy } catch (Exception ex) { log.error(ex); } */ ----------String--------------
構(gòu)造: String(String original):把字符串?dāng)?shù)據(jù)封裝成字符串對(duì)象
String(char[] value):把字符數(shù)組的數(shù)據(jù)封裝成字符串對(duì)象
String(char[] value, int index, int count):把字符數(shù)組中的一部分?jǐn)?shù)據(jù)
方法: 判斷功能:
boolean equals(Object obj):比較字符串的內(nèi)容是否相同
boolean equalsIgnoreCase(String str):比較字符串的內(nèi)容是否相同,忽略大小寫
boolean startsWith(String str):判斷字符串對(duì)象是否以指定的str開頭
boolean endsWith(String str):判斷字符串對(duì)象是否以指定的str結(jié)尾
獲取功能:
int length():獲取字符串的長(zhǎng)度,其實(shí)也就是字符個(gè)數(shù)
char charAt(int index):獲取指定索引處的字符
int indexOf(String str):獲取str在字符串對(duì)象中第一次出現(xiàn)的索引
String substring(int start):從start開始截取字符串
String substring(int start,int end):從start開始,到end結(jié)束截取字符串。包括start,不包括end
轉(zhuǎn)換功能:
char[] toCharArray():把字符串轉(zhuǎn)換為字符數(shù)組
String toLowerCase():把字符串轉(zhuǎn)換為小寫字符串
String toUpperCase():把字符串轉(zhuǎn)換為大寫字符串
String replace(char oldChar, char newChar)通過用 newChar 替換此字符串中出現(xiàn)的所有 oldChar ,返回處理后的字符串。
其它功能: String trim():去除字符串兩端空格
String[] split(String str):按照指定符號(hào)分割字符串
--------StringBuider(可變字符串)------------ 構(gòu)造: 就一個(gè)
方法: public int capacity():返回當(dāng)前容量 (理論值)
public int length():返回長(zhǎng)度(已經(jīng)存儲(chǔ)的字符個(gè)數(shù))
public StringBuilder append( 任意類型 ):添加數(shù)據(jù),并返回添加的數(shù)據(jù)
public StringBuilder reverse():反轉(zhuǎn)功能
StringBuilder replace(int start, int end, String str) 使用給定 String 中的字符替換此序列的子字符串中的字符。
--------Integer(包裝類)--------------- 構(gòu)造: 不需要,直接類名.方法名調(diào)用,如下
方法: Integer.parseInt(String str):將字符串轉(zhuǎn)int類型(只能數(shù)字內(nèi)容的字符串,不然報(bào)錯(cuò))
---------ArrayList(集合)------------------- 構(gòu)造: ArrayList();就學(xué)了空參創(chuàng)建
方法: public boolean add(E e):添加元素,成功返回true,就業(yè)班學(xué)false public void add(int index,E element):在指定的索引處添加一個(gè)元素
public E get(int index):返回指定索引處的元素
public E set(int index,E element):修改指定索引處的元素,返回被修改的元素
public int size():返回集合中的元素的個(gè)數(shù)
public boolean remove(Object o):刪除指定的元素,返回刪除是否成功 E remove(int index) 移除此列表中指定位置上的元素,并返回刪除的數(shù)據(jù)。
---------FileWriter(輸出普通流)----------- 構(gòu)造: FileWriter(String fileName); 傳入一個(gè)文件的路徑
方法: void write(int c) 寫入一個(gè)字符,int類型傳入 void write(String str) 寫入一個(gè)字符串 void write(String str, int startIndex, int len)寫入字符串的一部分 void write(char[] cbuf) 寫入一個(gè)字符數(shù)組 void write(char[] cbuf, int startIndex, int len)寫入字符數(shù)組的一部分
void flush() 將內(nèi)存中的數(shù)據(jù)刷新到文件中
void close() 數(shù)據(jù)刷新到文件中,關(guān)流釋放系統(tǒng)底層資源(關(guān)閉后永久關(guān)閉,直到下次程序運(yùn)行)
---------BufferedWriter(輸出緩沖流)----------- 構(gòu)造: BufferedWriter(new FileWriter(String fileName));傳入一個(gè)FileWriter對(duì)象,FileWriter包含一個(gè)文件的路徑
方法 (同F(xiàn)ileWriter,多了一個(gè)方法): void newLine() 寫入換行(\r\n)
---------FileReader(輸入普通流)----------- 構(gòu)造: FileReader(String fileName); 傳入一個(gè)文件的路徑
方法: int read() 讀取單個(gè)字符,若是讀取成功返回參數(shù)的int類型表現(xiàn)形式,若讀取失敗,返回-1 int read(char[] cbuf) 讀取指定char數(shù)組長(zhǎng)度個(gè)字符,并存入char數(shù)組,若是讀到文件尾部,則停止讀取,并返回讀取字符的個(gè)數(shù)(不是char數(shù)組長(zhǎng)度),若是一個(gè)都沒讀到,返回-1。 int read(char[] cbuf, int startIndex, int len) 讀取 startIndex 索引開始, len 個(gè)字符(length簡(jiǎn)拼)
void reset() 重置流(刪除前面讀的記錄)
---------BufferedReader(輸入緩沖流)----------- 構(gòu)造: FileReader(String fileName); 傳入一個(gè)文件的路徑
方法 (同F(xiàn)ileReader,多了一個(gè)方法) String ReadLine() 一次讀一行的內(nèi)容,返回讀到的內(nèi)容,沒讀到返回null
-----------Arrays(工具類,考試不推薦使用)----------------- 構(gòu)造: 不需要構(gòu)造,因?yàn)樵擃惒恍枰獎(jiǎng)?chuàng)建對(duì)象
方法: String toString(各種數(shù)組,集合不行) 返回該數(shù)組的全部?jī)?nèi)容的特定格式(遍歷數(shù)組)
方法重載: 1.方法名相同 2.參數(shù)列表不同(數(shù)量、類型、順序)
方法覆蓋: 1.訪問修飾符相同或更寬 2.返回值類型相同 3.方法名相同 4.參數(shù)表相同 5.static 靜態(tài)只能覆蓋靜態(tài) 非靜態(tài)只能覆蓋非靜態(tài) 6.子類方法不能拋出比父類更多的異常
三大修飾符:
static
可以修飾屬性、方法和初始化代碼塊,不可以修飾局部變量
1. 靜態(tài)屬性、方法為全類所有,可通過類名直接調(diào)用 2. 靜態(tài)初始化代碼塊在類加載時(shí)執(zhí)行,僅執(zhí)行一次
final
可以修飾局部變量、成員變量、方法和類
1. final修飾的變量一旦被賦值,就不能改變 2. final修飾的方法不可以被覆蓋 3. final修飾的類不能被繼承
abstract
可以修飾類和方法
1. 抽象類只能聲明引用,不能創(chuàng)建對(duì)象 2. 抽象方法只有聲明,沒有實(shí)現(xiàn)(不寫代碼塊) 3. 如果一個(gè)類中有抽象方法,那這個(gè)類必須是抽象類 4. 子類繼承一個(gè)抽象類,如果不希望子類變成抽象類,那子類必須實(shí)現(xiàn)父類中的全部抽象方法
PS:多個(gè)修飾符修飾同一方法、類時(shí)的使用問題
1. abstract 不能與 final 一起修飾方法、類
抽象類、方法需要被繼承、覆蓋才可使用,final修飾的類、方法不可被繼承、覆蓋
2. abstract 不能與 private 一起修飾方法(private只能修飾內(nèi)部類)
理由同上,私有方法不能被繼承
3. abstract 不能與 static 一起修飾方法(static只能修飾類的成員,不能修飾類本身)
抽象類需要有子類的實(shí)現(xiàn)類才能調(diào)用內(nèi)部方法,而靜態(tài)類可以直接通過本類名調(diào)用內(nèi)部方法
4. private 與 static 與 final 可以連用(屬性、方法都可以)
權(quán)限修飾符:private default protect public 可以修飾方法 public default 可以修飾類
接口:interface
1. 接口是特殊的抽象類(interface 代替了 abstract class) 2. 接口中所有屬性都是公開靜態(tài)常量 3. 接口中所有方法都是公開抽象方法 4. 一個(gè)接口可以繼承多個(gè)接口(extends 多個(gè)接口,接口之間用逗號(hào)隔開) 5. 一個(gè)類只可以繼承一個(gè)父類,但是可以實(shí)現(xiàn)多個(gè)接口
PS: 抽象類與接口的不同點(diǎn)
1. 抽象類可以有構(gòu)造方法,接口不可以有構(gòu)造方法
2. 抽象類不可以多繼承,接口可以多繼承
接口的實(shí)現(xiàn)(被子類繼承):implements
1. 一個(gè)類實(shí)現(xiàn)接口,如果不希望作為抽象類,就必須實(shí)現(xiàn)接口中全部方法
接口的作用;
1. 接口與多繼承
1. 可以讓子類繼承主要類型,讓次要類型作為一個(gè)接口讓子類實(shí)現(xiàn). 2. 單繼承具備簡(jiǎn)單性(相對(duì)于多繼承),使用接口實(shí)現(xiàn)的多繼承并不會(huì)破壞其簡(jiǎn)單性
2. 接口與解耦合
接口抽象出子類中的共性,利用多態(tài)來解耦合
3. 接口回調(diào)
實(shí)現(xiàn)某些接口,由函數(shù)庫中方法自動(dòng)調(diào)用。
例: 定義實(shí)體類是實(shí)現(xiàn)Comrparable<E>接口(中的comepareTo方法,返回值為int) 在調(diào)用java.util.Arrays.sort數(shù)組排序方法時(shí),可以排序存放實(shí)體類的數(shù)組
Object類:
Object是所有類的父類,如果一個(gè)類沒有定義直接繼承的父類,就會(huì)直接繼承Object類(自動(dòng)加上extends Object)
所有的類都會(huì)繼承Object類中的全部公開方法。
Obeject類中的全部方法:
1. finalize
該方法在垃圾回收時(shí),被垃圾回收器調(diào)用
(什么是垃圾? -- 沒有引用指向的對(duì)象)
1. JVM中有自動(dòng)垃圾回收機(jī)制,程序員只需要?jiǎng)?chuàng)建對(duì)象、分配空間,不需要回收垃圾
2. JVM只有在內(nèi)存不夠用的時(shí)候才會(huì)進(jìn)行垃圾回收 (可能會(huì)浪費(fèi)空間,但減少了垃圾回收對(duì)CPU的占用)
2. getClass
作用:得到對(duì)象的"實(shí)際"類型
補(bǔ)充:instanceof 可看做是不是: 引用 instanceof 類型 該引用的實(shí)際類型 是不是 某類型
比較兩個(gè)對(duì)象的實(shí)際類型是不是相等:
1. 使用 instanceof 只能得出某對(duì)象的實(shí)際樂行是不是某類型的子類
2. 可以使用getClass得到 對(duì)象的實(shí)際類型
語法:m1.getClass() == m2.getClass()
3. equals
作用: 比較兩個(gè)對(duì)象
1. 可以在子類中覆蓋equals方法,作用為使兩個(gè)對(duì)象可以使用自定義的標(biāo)準(zhǔn)相互比較
2. 如果不覆蓋equals方法,默認(rèn)比較兩個(gè)對(duì)象的地址值(即使用 == 比較兩個(gè)引用類型)
3. 字符串類覆蓋了equals方法
覆蓋equals方法的五個(gè)步驟:
1. 判斷 this == obj (地址相同直接返回true)
2. 判斷 obj == null (this一定不是null,否則無法調(diào)用equals方法)
3. 判斷 兩個(gè)對(duì)象的實(shí)際類型是否相同(使用getClass方法)
4. 強(qiáng)制類型轉(zhuǎn)換
5. 依次比較兩個(gè)對(duì)象的屬性是否相等
4. toString
作用:打印
在控制臺(tái)打印對(duì)象時(shí),自動(dòng)調(diào)用該對(duì)象的toString方法
包裝類:
將基本數(shù)據(jù)類型封裝為對(duì)象數(shù)據(jù)類型:
int -- Integer char -- Character 其他基本數(shù)據(jù)類型 -- 首字母大寫
int Integer String 之間的相互轉(zhuǎn)換:
1. Integer ii = new Integer( int i )
Integer ii = new Integer( String s )
2. int i = ii.intValue()
int i = Integer.paresInt( String s )
3. String s = ii.toString()
String s = String.valueOf( int i )
正則表達(dá)式:
作用: 使用正則表達(dá)式可以匹配出想要的字符串
1. [] [a-zA-Z0-9] [1235] 中括號(hào)可以匹配多個(gè)字符,或者范圍內(nèi)字符,范圍使用-分隔,多組范圍直接連著寫
2. {} {5} {5,10} 限制前一個(gè)字符內(nèi)容長(zhǎng)度,或者長(zhǎng)度范圍,范圍使用逗號(hào)分隔
3. 特殊意義字符: \:轉(zhuǎn)義字符,想要使用\ 需要使用轉(zhuǎn)義字符 \\
+:放在字符后面,代表匹配一個(gè)或多個(gè)該字符,想要使用+,需要使用轉(zhuǎn)義字符 \\+ .:匹配任意一個(gè)字符,使用字符本身,需要轉(zhuǎn)義 \\.
\\d 匹配任意字母
\\w 匹配任意字母或者數(shù)字
( | ) 邏輯或,匹配 | 前面或者后面的字符,例:(J|j)ava 可以匹配 Java 或者 java
^: 代表必須是字符串的開頭,例:^[a-z] 字符串必須以小寫字母開頭
$: 代表前一個(gè)字符必須是匹配內(nèi)容的結(jié)尾,例:^[a-z][0-9]$ 字符串必須以數(shù)字結(jié)尾
\\_ 下劃線
內(nèi)部類:
成員內(nèi)部類:
1. 成員內(nèi)部類可以訪問外部類中所有的、靜態(tài)的、私有的屬性和方法
2. 成員內(nèi)部類中不可以定義靜態(tài)的屬性和方法
3. 創(chuàng)建成員內(nèi)部類對(duì)象,需要先創(chuàng)建一個(gè)外部類對(duì)象(依賴于獨(dú)立的外部類對(duì)象,因此不可以有靜態(tài)成員)
創(chuàng)建成員內(nèi)部類對(duì)象:
外部類 out = new 外部類();
外部類.內(nèi)部類 引用名 = out.new 外部類.內(nèi)部類();
(類型是 外部類.內(nèi)部類,作為一個(gè)外部類的成員,需要用一個(gè)外部類對(duì)象來創(chuàng)建)
靜態(tài)內(nèi)部類:
1. 靜態(tài)內(nèi)部類只能訪問外部類中所有的靜態(tài)屬性和方法
2. 靜態(tài)內(nèi)部類可以定義普通的和靜態(tài)的屬性和方法
3. 創(chuàng)建靜態(tài)內(nèi)部類對(duì)象,可以直接使用該類的類型創(chuàng)建(靜態(tài)成員不依賴于外部類的對(duì)象)
創(chuàng)建靜態(tài)內(nèi)部類對(duì)象:
外部類.靜態(tài)內(nèi)部類 引用名 = new 外部類.靜態(tài)內(nèi)部類();
(不依賴外部類對(duì)象,直接用類型創(chuàng)建)
局部?jī)?nèi)部類:
作用同下
匿名內(nèi)部類:
new 接口名() { 接口的實(shí)現(xiàn)代碼 }
用途:
需要一個(gè)僅僅使用一次的對(duì)象時(shí),直接在方法內(nèi)部創(chuàng)建、使用,不需要打斷思路,另開一個(gè)實(shí)現(xiàn)類
缺點(diǎn):
代碼可讀性差
集合框架:
為什么使用集合: 數(shù)組的擴(kuò)容、插入、刪除操作十分繁瑣
集合的類型:
Collection<Object> 接口
--> List<Object> 接口
--> Set<Object> 接口
Map<Key, Value> 接口
集合中的方法:
Collecion :
add (Object obj) -- boolean 添加元素
contains (Object obj) -- boolean 查看是否包含某元素
isEmpty() -- boolean 集合是否為空
remove (Object obj) -- boolean 刪除某元素
clear() -- void 清空集合
size() -- int 查看集合中元素個(gè)數(shù)
List : 元素是對(duì)象類型,元素有下標(biāo)(有順序),元素可以重復(fù)
add (Object obj) / add (int index, Object obj)
添加元素,可以直接添加,或者插入到指定的index
get (int index) set (int index, Object obj)
根據(jù)下標(biāo),獲取或者修改元素
indexOf (Object obj) -- int
獲取元素下標(biāo)
Set:元素是對(duì)象類型,元素沒有下標(biāo)(沒有順序),元素不可以重復(fù)
Set集合沒有自己特有的方法,全部方法繼承自Collection
Map:元素是鍵值對(duì)類型,鍵不可以重復(fù),值可以重復(fù)
get (Object key) -- Object
根據(jù)鍵,獲取對(duì)應(yīng)的值
put (Object key, Object value) -- void
添加一個(gè)鍵值對(duì)
remove (Object key) -- void
刪除一個(gè)鍵值對(duì),根據(jù)值
ketSet() -- Set
獲取全部的鍵,放到一個(gè)Set里面返回
values() -- Collection
獲取全部的值,放到一個(gè)Collection中返回
containsKey/containsValus
查看Map中是否包含某個(gè)Key/Values
size()
查看Map中鍵值對(duì)個(gè)數(shù)
isEmpty()
clear()
entrySet()
獲取全部的鍵值對(duì)(Map.Entry類型),放到Set中返回
集合的實(shí)現(xiàn)類:
List 的實(shí)現(xiàn)類:
ArrayList
1. 使用數(shù)組實(shí)現(xiàn)
2. 增刪慢,查詢快
LinkedList
1. 使用鏈表實(shí)現(xiàn)
2. 增刪快,查詢慢
Vector
1. JDK1.0遺留的產(chǎn)物
2. 重量級(jí),線程安全,速度慢(多線程訪問同一對(duì)象時(shí),不會(huì)出現(xiàn)同步問題)
Set 的實(shí)現(xiàn)類:
HashSet
1. 集合中的元素?zé)o序,不重復(fù)(可以用來去除一組元素中重復(fù)的數(shù)據(jù))
2. new HashSet() 默認(rèn)容量16,加載因子0.75
3. newHashSet(int 容量, float )
LinkedHashSet
1. 遍歷時(shí)可以保留添加到集合中的順序(Set集合中的元素是無序的)
Set 集合是如何實(shí)現(xiàn)不重復(fù)元素的?
添加進(jìn)Set集合中的元素要想做到不重復(fù)需要:
1. 需要覆蓋 equals() 方法 -- 變成比較元素內(nèi)容而不是比較元素地址
2. 需要覆蓋 hashCode() 方法 -- 使哈希碼與元素內(nèi)容有關(guān),
保證相同元素有相同哈希碼,
盡量保證不同元素哈希碼不同,
可節(jié)省運(yùn)算、比較次數(shù)
如何實(shí)現(xiàn)元素不重復(fù)的?
1. 每個(gè)對(duì)象都有自己的 hashCode(hashSet使用數(shù)組加鏈表實(shí)現(xiàn))
-- hashCode決定對(duì)象在集合中的存放位置,
初始hashCode值由對(duì)象地址決定
2. 如果兩個(gè)對(duì)象的hashCode相同,就使用 equals() 方法進(jìn)行比較,
去掉重復(fù)元素,不重復(fù)的掛到該hashCode對(duì)應(yīng)數(shù)組位置中的鏈表里
3. 如果兩個(gè)對(duì)象hashCode不同,那么放入集合的位置就可能不同,
兩個(gè)對(duì)象就不會(huì)進(jìn)行 equals() 方法比較的過程,因此必須修改hashCode方法
讓內(nèi)容可能相同的對(duì)象hashCode相同,進(jìn)行比較去重復(fù)。
同時(shí)也要盡量保證內(nèi)容不同的對(duì)象的hashCode不同,盡量加快運(yùn)算速度。
equals方法:
1. 判斷兩個(gè)對(duì)象地址是否相同(直接等于)
2. 判斷參數(shù)對(duì)象是否為空
3. 判斷兩個(gè)對(duì)象類型是否相同(使用getClass方法)
使用 instanceof 有可能遇到父子類的情況
4. 將參數(shù)對(duì)象類型強(qiáng)轉(zhuǎn)成本類對(duì)象類型
5. 逐個(gè)比較兩個(gè)對(duì)象的屬性
Map 的實(shí)現(xiàn)類:
HashMap
1. 鍵不可以重復(fù),同樣需要覆蓋 equals 方法和 hashCode 方法
2. 允許鍵/值為 null
LinkedHashMap
1. 遍歷時(shí),保留了鍵的放入順序
HashTable
1. 類似于 Vector ,重量級(jí),速度慢,線程安全
2. 當(dāng)鍵/值為 null 時(shí),會(huì)拋出異常
Map 集合的三種遍歷方式:
鍵遍歷:
使用 keySet() 方法,拿到全部鍵的Set,再遍歷 Set 即可(配合 get(key) 方法拿值)
值遍歷:
使用 values() 方法,拿到全部值的Collection
鍵值對(duì)遍歷:
1.使用 entrySet() 方法,拿到全部的鍵值對(duì)Set
裝有鍵值對(duì)的Set的泛型需要注意寫法:
例: Set<Map.Entry<Integer, String>> set = map.entrySet();
鍵值對(duì)的類型為:Map.Entry , 例: Map.Entry entry = (Map.Entry)iter.next();
鍵值對(duì)的迭代器遍歷時(shí),需要將從Set中取出
的值強(qiáng)轉(zhuǎn)成 Map.Entry 類型
↑↑以上是JDK5.0之前泛型沒出的時(shí)候的做法
加泛型之后,不需要在強(qiáng)轉(zhuǎn)了
2. 使用Map.Entry類中的 getKey() / getValue() 方法,獲取鍵值對(duì)中的鍵和值
PS:用迭代器遍歷集合
Iterator iter = list.iterator(); --> List 和 Set 中有iterator方法,獲取迭代器
//創(chuàng)建一個(gè)迭代器對(duì)象
while( iter.hasNext() ) {
Object value = iter.next();
//對(duì)拿到的value進(jìn)行需要的操作
}
foreach遍歷
1. foreach封裝了迭代器遍歷
2. 迭代器對(duì)與集合長(zhǎng)度及變化做了安全監(jiān)測(cè),
3. 定義了異常:ConcurrentModificationException 并發(fā)修改異常
4. 在使集合創(chuàng)建迭代器時(shí),會(huì)為變量expectedModCount賦值(賦予當(dāng)前modCount的值)
5. foreach遍歷集合時(shí),先調(diào)用hasNext方法,指針后移,如果索引等于集合長(zhǎng)度,
則結(jié)束循環(huán),如果索引小于集合長(zhǎng)度,
則通過next()取出指針指向的集合內(nèi)對(duì)象地址,執(zhí)行循環(huán)體。
6. 在next()中進(jìn)行集合長(zhǎng)度及變化的安全監(jiān)測(cè),如果索引大于集合長(zhǎng)度,則說明在
上一次循環(huán)的循環(huán)體中,出現(xiàn)了修改集合長(zhǎng)度的操作,則直接拋出
并發(fā)修改異常;集合之中有一個(gè)成員變量modCount,
記錄了集合被增刪元素的次數(shù),next()中會(huì)先比較expectedModCount和
modCount的值是否相同,及監(jiān)測(cè)集合有沒有被修改過,如果不同就拋出
并發(fā)修改異常
PS: 7. 安全監(jiān)測(cè)是在next方法中進(jìn)行的,因此若是刪除集合的倒數(shù)第二個(gè)元素:
在循環(huán)體執(zhí)行刪除語句,刪除后集合長(zhǎng)度-1,循環(huán)體結(jié)束進(jìn)入下一次循環(huán)判斷
hasNext方法:索引長(zhǎng)度剛好等于集合長(zhǎng)度,結(jié)束循環(huán),不進(jìn)入next方法。
所以:可以在foreach遍歷集合中,刪除倒數(shù)第二個(gè)元素。
8. iterator的remove方法對(duì)集合修改安全監(jiān)測(cè)進(jìn)行了屏蔽處理,
使用iterator中的方法刪除元素,不會(huì)拋出異常
結(jié)論:Iterator做出了安全監(jiān)測(cè),集合對(duì)象不可以在foreach循環(huán)遍歷集合中,
做出增加刪除元素的操作,否則拋出并發(fā)修改異常。
(除了刪除倒數(shù)第二個(gè)元素)
集合工具類:
Collections :(靜態(tài)方法)
1. Collections.shuffle(list) 打亂一個(gè)List集合中元素的排列順序
2. Collections.sort(list) 按照自然順序排序一個(gè)List集合內(nèi)的元素
3. Collections 只能作用于List集合
Properties:持久的屬性集
1. Properties繼承自Map集合
2. Properties中有方法可以將集合中內(nèi)容保存在文本文件中
3. Properties限定泛型,只能裝String類型數(shù)據(jù)(name,value)
4. Properties中的常用方法:
1. setProperties(String, String)
2. getProperties(String key)
3. stringPropertyNames(獲取集合中全部的name的 Set 集合)
4. store(OutputStream,String comments) -- 將集合中數(shù)據(jù)通過輸出流保存在文本文件中
自定義一個(gè)輸出流,文本文件必須以.properties結(jié)尾,commetns為注釋,可以為null
5. load(InputStream) -- 通過一個(gè)輸入流將文件中內(nèi)容傳入Properties對(duì)象中
|