第二章 一切都是對(duì)象
java棧中保存類的引用孽查,堆中保存類。
創(chuàng)建一個(gè)數(shù)組的時(shí)候炸庞,等于創(chuàng)建了一個(gè)引用數(shù)組辜荠。
static:類變量帚呼,可以用實(shí)例變量訪問,也可以直接用類名訪問。
第三章 操作符
無需考慮移植問題狗热,所以沒有sizeof()
>>:有符號(hào)右移
>>>:無符號(hào)右移
第四章 控制執(zhí)行流程
foreach:遍歷數(shù)組和容器
label + break | continue 實(shí)現(xiàn) goto的功能驰怎。極少用
第五章 初始化與清理
構(gòu)造器的名字與類相同阐滩,故每個(gè)方法的手寫字母小寫的編碼風(fēng)格不適合構(gòu)造函數(shù)。
構(gòu)造方法實(shí)際上是靜態(tài)方法县忌。
this表示當(dāng)前實(shí)例掂榔。只有需要區(qū)分時(shí)引用。
this():調(diào)用構(gòu)造函數(shù)
super():調(diào)用父類構(gòu)造函數(shù)
必須位于構(gòu)造函數(shù)的第一行症杏,且兩者不能共存装获。
static(類)方法中沒有this指針。
static方法不能調(diào)用非static方法厉颤,反過來可以穴豫。
finalize():調(diào)用本地方法(C/C++)的時(shí)候,確保一些資源釋放逼友。很少用精肃。
初始化順序:
1. 父類構(gòu)造 2. 成員初始化(按定義順序) 3. 派生類構(gòu)造秤涩。
static代碼段,會(huì)依據(jù)程序中使用到的順序肋杖,依次初始化溉仑。
銷毀的順序:與初始化相反。
初始化順序舉例:
可變參數(shù)列表:
Object... args:其實(shí)就是在內(nèi)部進(jìn)行了一次的數(shù)組參數(shù)轉(zhuǎn)換状植,不用顯示的寫數(shù)組浊竟。
第六章 訪問控制權(quán)限
字段&方法訪問權(quán)限
public :都可以
protect :同一個(gè)包以及派生類
default :同一個(gè)包
private :僅內(nèi)部
java沒有C的條件編譯,采用import導(dǎo)包津畸。
java用包名替代命名空間的作用振定。
類訪問權(quán)限:
public
default:包訪問權(quán)限
一個(gè)class文件中,只能有一個(gè)public類肉拓。
第七章 復(fù)用類
has a
is a
java的方法重載可以在基類與派生類之間進(jìn)行后频,而C++不行。
提供override暖途,派生類重寫基類方法卑惜。
final字段:編譯時(shí)常量,定義時(shí)賦值驻售,一般需要加上static露久。
空白final:定義時(shí)沒有賦值,此時(shí)需要在構(gòu)造器中賦值欺栗。
final參數(shù):類似C++的const
final方法:不會(huì)被派生類覆蓋毫痕,相對(duì)高效(差別不大)。private方法迟几,隱式為final方法消请。
final類:無法被繼承。
第八章 多態(tài)
向上轉(zhuǎn)型:父類引用指向子類對(duì)象类腮,子類擴(kuò)展的方法不可用臊泰。
向下轉(zhuǎn)型:需要保證之前確實(shí)是子類對(duì)象給了父類引用。
前期綁定(靜態(tài)綁定)
后期綁定(動(dòng)態(tài)綁定)
java中除了static方法和final(private)方法存哲,都是動(dòng)態(tài)綁定因宇,C++只有virtual函數(shù)是動(dòng)態(tài)綁定。
基類構(gòu)造函數(shù)調(diào)用動(dòng)態(tài)方法祟偷。調(diào)用的是派生類的方法察滑,但是派生類的變量此時(shí)還沒有賦值,是默認(rèn)初始值修肠。
第九章 接口
抽象類:含有至少一個(gè)抽象方法贺辰,abstract修飾。單繼承
接口:多繼承。
接口中的字段:都是static final的饲化。
接口訪問:public default
接口中的方法:自動(dòng)是public
接口可以實(shí)現(xiàn)多繼承
接口可以繼承接口
接口多繼承莽鸭,如果存在函數(shù)沖突,會(huì)報(bào)錯(cuò)吃靠。
第十章 內(nèi)部類
可以訪問外部類private域
外部類名.this :訪問外部類的this
外部類名.new 內(nèi)部類:創(chuàng)建內(nèi)部類硫眨。
匿名內(nèi)部類:一次性使用。
第十一章 持有對(duì)象
泛型(<>中指定的類型)巢块,使得編譯器進(jìn)行檢查礁阁,而不會(huì)導(dǎo)致將錯(cuò)誤類型放入到容器中。
List:插入有序族奢,不能隨意
Set:數(shù)據(jù)唯一
Map:鍵值對(duì)
Queue:隊(duì)列
第十二章 通過異常處理錯(cuò)誤
Java 異常結(jié)構(gòu)
非檢查異常(unckecked exception):Error 和 RuntimeException 以及他們的子類姥闭。
檢查異常(checked exception):除了Error 和 RuntimeException的其它異常。
throw:執(zhí)行語(yǔ)句越走,直接拋出異常類
throws:用在方法后棚品,標(biāo)識(shí)該方法可拋出的異常,可以接多個(gè)廊敌。
try: 可能發(fā)生異常的語(yǔ)句
catch: 可有多個(gè)铜跑,按順序捕捉,一般從小到大覆蓋所有可能骡澈。
finally:資源釋放等必須執(zhí)行的語(yǔ)句疼进。
try塊中即便有return,break秧廉,continue等改變執(zhí)行流的語(yǔ)句,finally也會(huì)執(zhí)行拣帽。
Exception: 自定義異常一般需要繼承自這個(gè)類疼电。
第十三章 字符串
String 為字符串常量,而StringBuilder和StringBuffer均為字符串變量
StringBuilder 是線程不安全的减拭,而StringBuffer是線程安全的
StringBuilder: 適用于單線程下在字符緩沖區(qū)進(jìn)行大量操作的情況
StringBuffer: 適用多線程下在字符緩沖區(qū)進(jìn)行大量操作的情況
編譯器會(huì)用StringBuilder優(yōu)化一些String操作蔽豺,避免大量生成無用的中間字符串。
格式化輸出
System.out.printf();
System.out.format();
String.format();
正則表達(dá)式
split():將字符串從正則匹配的地方切開拧粪。
第十四章 類型信息
加載類的一些準(zhǔn)備:
限定RTTI的類型
<修陡?> 通配符
<?extends Object>
<? super Object>
obj.instanceof(class)
class.inInstance(obj)
1.一個(gè)對(duì)象是本身類的一個(gè)對(duì)象
2.一個(gè)對(duì)象是其基類和接口的一個(gè)對(duì)象
3.所有對(duì)象都是Object
4.凡是null有關(guān)的都是false null.instanceof(class)
類名.class和對(duì)象.getClass()幾乎沒有區(qū)別可霎,因?yàn)橐粋€(gè)類被類加載器加載后魄鸦,就是唯一的一個(gè)類。
反射
Class類與java.lang.reflect類庫(kù)一起對(duì)反射進(jìn)行了支持癣朗,該類庫(kù)包含F(xiàn)ield拾因、Method和Constructor類,這些類的對(duì)象由JVM在啟動(dòng)時(shí)創(chuàng)建,用以表示未知類里對(duì)應(yīng)的成員绢记。這樣的話就可以使用Contructor創(chuàng)建新的對(duì)象扁达,用get()和set()方法獲取和修改類中與Field對(duì)象關(guān)聯(lián)的字段,用invoke()方法調(diào)用與Method對(duì)象關(guān)聯(lián)的方法蠢熄。另外跪解,還可以調(diào)用getFields()、getMethods()和getConstructors()等許多便利的方法签孔,以返回表示字段叉讥、方法、以及構(gòu)造器對(duì)象的數(shù)組骏啰,這樣节吮,對(duì)象信息可以在運(yùn)行時(shí)被完全確定下來,而在編譯時(shí)不需要知道關(guān)于類的任何事情判耕。
動(dòng)態(tài)代理
Java的動(dòng)態(tài)代理可以動(dòng)態(tài)地創(chuàng)建并代理并動(dòng)態(tài)地處理對(duì)所代理方法的調(diào)用透绩。在動(dòng)態(tài)代理上所做的所有調(diào)用都會(huì)被重定向到單一的調(diào)用處理器上,它的工作是揭示調(diào)用的類型并確定相應(yīng)的策略壁熄。
// 原始類與接口
public interface Interface {
void doSomething();
void somethingElse(String arg);
}
public class RealObject implements Interface {
public void doSomething() {
System.out.println("doSomething.");
}
public void somethingElse(String arg) {
System.out.println("somethingElse " + arg);
}
}
// 動(dòng)態(tài)代理類
public class DynamicProxyHandler implements InvocationHandler {
private Object proxyed;
public DynamicProxyHandler(Object proxyed) {
this.proxyed = proxyed;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
System.out.println("代理工作了.");
return method.invoke(proxyed, args);
}
}
// client
public class Main {
public static void main(String[] args) {
RealObject real = new RealObject();
Interface proxy = (Interface) Proxy.newProxyInstance(
Interface.class.getClassLoader(), new Class[] {Interface.class},
new DynamicProxyHandler(real));
proxy.doSomething();
proxy.somethingElse("luoxn28");
}
}
通過調(diào)用Proxy靜態(tài)方法Proxy.newProxyInstance()可以創(chuàng)建動(dòng)態(tài)代理帚豪,這個(gè)方法需要得到一個(gè)類加載器,一個(gè)你希望該代理實(shí)現(xiàn)的接口列表(不是類或抽象類)草丧,以及InvocationHandler的一個(gè)實(shí)現(xiàn)類狸臣。
動(dòng)態(tài)代理可以將所有調(diào)用重定向到調(diào)用處理器,因此通常會(huì)調(diào)用處理器的構(gòu)造器傳遞一個(gè)”實(shí)際”對(duì)象的引用昌执,從而將調(diào)用處理器在執(zhí)行中介任務(wù)時(shí)烛亦,將請(qǐng)求轉(zhuǎn)發(fā)。
第十五章 泛型
泛型類似C++中的模板懂拾,增加編譯時(shí)安全檢查煤禽,同時(shí)使得同一個(gè)算法應(yīng)用于不同的數(shù)據(jù)類型,增加代碼復(fù)用性岖赋。
泛型可用于:接口檬果、方法、匿名內(nèi)部類唐断、類中选脊。
在泛型方法內(nèi)部,無法獲得有關(guān)泛型參數(shù)的信息脸甘。java泛型擦除了類型信息恳啥,因此List<Integer> 和 List<String> 是一樣的。
引入通配符限定泛型的范圍斤程。
<角寸?> 通配符
<菩混?extends Object>
<? super Object>
- 任何基本類型都不能作為泛型的參數(shù)。
泛型由于類型擦除扁藕,無法被catch捕捉到沮峡,也無法被繼承Throwable。
第十七章 容器深入研究
正確的equals要滿足的條件
第十八章 java IO系統(tǒng)
基于字節(jié)的IO操作
基于字符的IO操作
序列化和反序列化的概念
把對(duì)象轉(zhuǎn)換為字節(jié)序列的過程稱為對(duì)象的序列化亿柑。
把字節(jié)序列恢復(fù)為對(duì)象的過程稱為對(duì)象的反序列化邢疙。
對(duì)象的序列化主要有兩種用途:
1) 把對(duì)象的字節(jié)序列永久地保存到硬盤上,通常存放在一個(gè)文件中望薄;
2) 在網(wǎng)絡(luò)上傳送對(duì)象的字節(jié)序列疟游。
只有實(shí)現(xiàn)了Serializable或Externalizable接口的類的對(duì)象才能被序列化。Externalizable接口繼承自 Serializable接口痕支,實(shí)現(xiàn)Externalizable接口的類完全由自身來控制序列化的行為颁虐,而僅實(shí)現(xiàn)Serializable接口的類可以 采用默認(rèn)的序列化方式 。
對(duì)象序列化包括如下步驟:
1) 創(chuàng)建一個(gè)對(duì)象輸出流卧须,它可以包裝一個(gè)其他類型的目標(biāo)輸出流另绩,如文件輸出流;
2) 通過對(duì)象輸出流的writeObject()方法寫對(duì)象花嘶。
對(duì)象反序列化的步驟如下:
1) 創(chuàng)建一個(gè)對(duì)象輸入流笋籽,它可以包裝一個(gè)其他類型的源輸入流,如文件輸入流椭员;
2) 通過對(duì)象輸入流的readObject()方法讀取對(duì)象车海。
serialVersionUID
凡是實(shí)現(xiàn)Serializable接口的類都有一個(gè)表示序列化版本標(biāo)識(shí)符的靜態(tài)變量
private static final long serialVersionUID = -5809782578272943999L;
serialVersionUID的取值是Java運(yùn)行時(shí)環(huán)境根據(jù)類的內(nèi)部細(xì)節(jié)自動(dòng)生成,任何修改都可能變化隘击。
用不同的Java編譯器編譯侍芝,有可能會(huì)導(dǎo)致不同的 serialVersionUID,也有可能相同埋同。
為了提高serialVersionUID的獨(dú)立性和確定性竭贩,強(qiáng)烈建議在一個(gè)可序列化類中顯示的定義serialVersionUID,為它賦予明確的值莺禁。
顯式地定義serialVersionUID有兩種用途:
1. 在某些場(chǎng)合,希望類的不同版本對(duì)序列化兼容窄赋,因此需要確保類的不同版本具有相同的serialVersionUID哟冬;
2. 在某些場(chǎng)合,不希望類的不同版本對(duì)序列化兼容忆绰,因此需要確保類的不同版本具有不同的serialVersionUID浩峡。
第二十一章 并發(fā)
實(shí)現(xiàn)Runnable接口中的run方法:不返回任何值。
實(shí)現(xiàn)Callable接口中的call方法:可以返回值错敢。必須從ExecutorService,submit()中使用它翰灾。
繼承自Thread
sleep():不釋放鎖缕粹。
yield():具有相同優(yōu)先級(jí)的線程先運(yùn)行。
setDaemon():后臺(tái)運(yùn)行纸淮。
join():等待加入線程完成后平斩,執(zhí)行。
線程狀態(tài)
死鎖條件——同時(shí)滿足
樂觀鎖和悲觀鎖
悲觀鎖:總是假設(shè)最壞的情況咽块,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改绘面,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖侈沪。
傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)里邊就用到了很多這種鎖機(jī)制揭璃,比如行鎖,表鎖等亭罪,讀鎖瘦馍,寫鎖等,都是在做操作之前先上鎖应役。再比如Java里面的同步原語(yǔ)synchronized關(guān)鍵字的實(shí)現(xiàn)也是悲觀鎖情组。
樂觀鎖:每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖扛吞,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒有去更新這個(gè)數(shù)據(jù)呻惕,可以使用版本號(hào)、CAS等機(jī)制滥比。
樂觀鎖適用于多讀的應(yīng)用類型亚脆,這樣可以提高吞吐量,像數(shù)據(jù)庫(kù)提供的類似于write_condition機(jī)制盲泛,其實(shí)都是提供的樂觀鎖濒持。在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實(shí)現(xiàn)方式CAS實(shí)現(xiàn)的。
version方式:一般是在數(shù)據(jù)表中加上一個(gè)數(shù)據(jù)版本號(hào)version字段寺滚,表示數(shù)據(jù)被修改的次數(shù)柑营,當(dāng)數(shù)據(jù)被修改時(shí),version值會(huì)加一村视。當(dāng)線程A要更新數(shù)據(jù)值時(shí)官套,在讀取數(shù)據(jù)的同時(shí)也會(huì)讀取version值,在提交更新時(shí)蚁孔,若剛才讀取到的version值為當(dāng)前數(shù)據(jù)庫(kù)中的version值相等時(shí)才更新奶赔,否則重試更新操作,直到更新成功杠氢。
CAS操作方式:即compare and swap 或者 compare and set站刑,涉及到三個(gè)操作數(shù),數(shù)據(jù)所在的內(nèi)存值鼻百,預(yù)期值绞旅,新值摆尝。當(dāng)需要更新時(shí),判斷當(dāng)前內(nèi)存值與之前取到的值是否相等因悲,若相等堕汞,則用新值更新,若失敗則重試囤捻,一般情況下是一個(gè)自旋操作臼朗,即不斷的重試。