Java類(lèi)集
1、Collection 是存放一組單值得最大接口,所謂的單值是指集合中的每個(gè)元素都是一個(gè)對(duì)象,一般會(huì)很少直接使用此接口直接操作。
2、List 是Collection接口的子接口,也是最常用的接口,此接口對(duì)Collection接口進(jìn)行了大量的擴(kuò)充。里面的內(nèi)容是允許重復(fù)的。
3、Set 是Collection接口的子類(lèi),沒(méi)有對(duì)Collection進(jìn)行擴(kuò)充,里面不允許存放重復(fù)的內(nèi)容。
4、Map Map是存放一對(duì)值的最大接口,即,接口中每個(gè)元素都是一對(duì),以key—>value的形式保存。
5、Iterator 集合的輸出接口,用于輸出集合中的內(nèi)容只能進(jìn)行從前到后的單向輸出。
6、ListIterator 是Iterator的子接口,可以進(jìn)行雙向輸出。
7、Enumeration 是最早的輸出接口,用于輸出指定集合中的內(nèi)容。
8、SortedSet 單值的排序接口,凡是實(shí)現(xiàn)此接口的集合類(lèi),里面的內(nèi)容是可以排序的,使用比較器排序。
9、SortedMap 存放一對(duì)值的排序接口,實(shí)現(xiàn)此接口的集合類(lèi),里面的內(nèi)容按照key排序,使用比較器排序。
10、Queue 隊(duì)列接口,此接口的子類(lèi)可以實(shí)現(xiàn)隊(duì)列操作。
11、Map.Entry Map.Entry的內(nèi)部接口,每個(gè)Map.Entry對(duì)象都保存著一對(duì)key—>value的內(nèi)容,每個(gè)Map接口中都保存著多個(gè)Map.Entry接口實(shí)例。
以上的接口必須全部掌握。并且掌握各個(gè)接口的主要特點(diǎn)。
接口的繼承關(guān)系
Map接口:
String和equals()、hashCode()
Object中的“==”,equal,hashCode()
Object中的==
- 對(duì)于基本數(shù)據(jù)類(lèi)型,“==”比較值是否相同。
- 對(duì)于引用數(shù)據(jù)類(lèi)型, “==”比較內(nèi)存中的存放地址是否相同。
Object中的equals()
public boolean equals(Object o) {
return this == o;
}
Object的equals()方法默認(rèn)還是根據(jù)“==”比較,所以比較的還是內(nèi)存地址。
Object的equals()方法默認(rèn)還是根據(jù)“==”比較,所以比較的還是內(nèi)存地址。
public int hashCode() {
int lockWord = shadow$_monitor_;
final int lockWordStateMask = 0xC0000000; // Top 2 bits.
final int lockWordStateHash = 0x80000000; // Top 2 bits are value 2 (kStateHash).
final int lockWordHashMask = 0x0FFFFFFF; // Low 28 bits.
if ((lockWord & lockWordStateMask) == lockWordStateHash) {
return lockWord & lockWordHashMask;
}
return System.identityHashCode(this);
}
Object中的hashCode()
public int hashCode() {
int lockWord = shadow$_monitor_;
final int lockWordStateMask = 0xC0000000; // Top 2 bits.
final int lockWordStateHash = 0x80000000; // Top 2 bits are value 2 (kStateHash).
final int lockWordHashMask = 0x0FFFFFFF; // Low 28 bits.
if ((lockWord & lockWordStateMask) == lockWordStateHash) {
return lockWord & lockWordHashMask;
}
return System.identityHashCode(this);
}
Object中的hashCode()返回值是在JVM中的32位地址。
String類(lèi)的“==”,equal,hashCode()
String類(lèi)中對(duì)hashCode()和equals()都進(jìn)行了重寫(xiě),所以調(diào)用String的equals()和hashCode()可能會(huì)和沒(méi)重寫(xiě)這兩個(gè)方法的類(lèi)產(chǎn)生不同的結(jié)果。
String的equals()
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (other instanceof String) {
String s = (String)other;
int count = this.count;
if (s.count != count) {
return false;
}
// TODO: we want to avoid many boundchecks in the loop below
// for long Strings until we have array equality intrinsic.
// Bad benchmarks just push .equals without first getting a
// hashCode hit (unlike real world use in a Hashtable). Filter
// out these long strings here. When we get the array equality
// intrinsic then remove this use of hashCode.
if (hashCode() != s.hashCode()) {
return false;
}
for (int i = 0; i < count; ++i) {
if (charAt(i) != s.charAt(i)) {
return false;
}
}
return true;
} else {
return false;
}
}
同樣是如果內(nèi)存地址相同肯定內(nèi)容也相同,返回true。
存儲(chǔ)地址不同,要滿(mǎn)足長(zhǎng)度、hash碼、對(duì)應(yīng)的字符都相同才能返回true。
String的hashCode()
@Override public int hashCode() {
int hash = hashCode;
if (hash == 0) {
if (count == 0) {
return 0;
}
for (int i = 0; i < count; ++i) {
hash = 31 * hash + charAt(i);
}
hashCode = hash;
}
return hash;
}
根據(jù)String的成員變量hashCode和字符串的內(nèi)容生成hashcode。
Spring工作原理
內(nèi)部最核心的就是IoC了,動(dòng)態(tài)注入(DI),讓一個(gè)對(duì)象的創(chuàng)建不用new了,可以自動(dòng)的生產(chǎn),這其實(shí)就是利用Java里的反射。反射其實(shí)就是在運(yùn)行時(shí)動(dòng)態(tài)的去創(chuàng)建、調(diào)用對(duì)象,Spring就是在運(yùn)行時(shí),跟xml Spring的配置
文件來(lái)動(dòng)態(tài)的創(chuàng)建對(duì)象,和調(diào)用對(duì)象里的方法的 。
Spring還有一個(gè)核心就是AOP這個(gè)就是面向切面編程,可以為某一類(lèi)對(duì)象 進(jìn)行監(jiān)督和控制(也就是在調(diào)用這類(lèi)對(duì)象的具體方法的前后去調(diào)用你指定的模塊)從而達(dá)到對(duì)一個(gè)模塊擴(kuò)充的功能。這些都是通過(guò)
配置類(lèi)達(dá)到的。
Spring目的:就是讓對(duì)象與對(duì)象(模塊與模塊)之間的關(guān)系沒(méi)有通過(guò)代碼來(lái)關(guān)聯(lián),都是通過(guò)配置類(lèi)說(shuō)明管理的(Spring根據(jù)這些配置 內(nèi)部通過(guò)反射去動(dòng)態(tài)的組裝對(duì)象)
要記?。篠pring是一個(gè)容器,凡是在容器里的對(duì)象才會(huì)有Spring所提供的這些服務(wù)和功能。
Spring里用的最經(jīng)典的一個(gè)設(shè)計(jì)模式就是:模板方法模式。
Spring AOP與IOC
一、 IoC(Inversion of control): 控制反轉(zhuǎn)
1、IoC:
概念:控制權(quán)由對(duì)象本身轉(zhuǎn)向容器;由容器根據(jù)配置文件去創(chuàng)建實(shí)例并創(chuàng)建各個(gè)實(shí)例之間的依賴(lài)關(guān)系
核心:bean工廠;在Spring中,bean工廠創(chuàng)建的各個(gè)實(shí)例稱(chēng)作bean
二、AOP(Aspect-Oriented Programming): 面向方面編程
1、 代理的兩種方式:
靜態(tài)代理:
- 針對(duì)每個(gè)具體類(lèi)分別編寫(xiě)代理類(lèi);
- 針對(duì)一個(gè)接口編寫(xiě)一個(gè)代理類(lèi);
動(dòng)態(tài)代理:
針對(duì)一個(gè)方面編寫(xiě)一個(gè)InvocationHandler,然后借用JDK反射包中的Proxy類(lèi)為各種接口動(dòng)態(tài)生成相應(yīng)的代理類(lèi)
JDK動(dòng)態(tài)代理的實(shí)現(xiàn)原理
首先來(lái)看一下如何使用JDK動(dòng)態(tài)代理。JDK提供了java.lang.reflect.Proxy類(lèi)來(lái)實(shí)現(xiàn)動(dòng)態(tài)代理的,可通過(guò)它的newProxyInstance來(lái)獲得代理實(shí)現(xiàn)類(lèi)。同時(shí)對(duì)于代理的接口的實(shí)際處理,是一個(gè)java.lang.reflect.InvocationHandler,它提供了一個(gè)invoke方法供實(shí)現(xiàn)者提供相應(yīng)的代理邏輯的實(shí)現(xiàn)??梢詫?duì)實(shí)際的實(shí)現(xiàn)進(jìn)行一些特殊的處理,像Spring AOP中的各種advice。下面來(lái)看看如何使用。
被代理的接口:
package com.mikan.proxy;
public interface HelloWorld {
void sayHello(String name);
}
接口的實(shí)現(xiàn)類(lèi):
package com.mikan.proxy;
public class HelloWorldImpl implements HelloWorld {
@Override
public void sayHello(String name) {
System.out.println("Hello " + name);
}
}
實(shí)現(xiàn)一個(gè)java.lang.reflect.InvocationHandler:
package com.mikan.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class CustomInvocationHandler implements InvocationHandler {
private Object target;
public CustomInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before invocation");
Object retVal = method.invoke(target, args);
System.out.println("After invocation");
return retVal;
}
}
使用代理:
package com.mikan.proxy;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) throws Exception {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
CustomInvocationHandler handler = new CustomInvocationHandler(new HelloWorldImpl());
HelloWorld proxy = (HelloWorld) Proxy.newProxyInstance(
ProxyTest.class.getClassLoader(),
new Class[]{HelloWorld.class},
handler);
proxy.sayHello("Mikan");
}
}
可以看到,動(dòng)態(tài)生成的代理類(lèi)有如下特性:
- 繼承了Proxy類(lèi),實(shí)現(xiàn)了代理的接口,由于java不能多繼承,這里已經(jīng)繼承了Proxy類(lèi)了,不能再繼承其他的類(lèi),所以JDK的動(dòng)態(tài)代理不支持對(duì)實(shí)現(xiàn)類(lèi)的代理,只支持接口的代理。
- 提供了一個(gè)使用InvocationHandler作為參數(shù)的構(gòu)造方法。
- 生成靜態(tài)代碼塊來(lái)初始化接口中方法的Method對(duì)象,以及Object類(lèi)的equals、hashCode、toString方法。
- 重寫(xiě)了Object類(lèi)的equals、hashCode、toString,它們都只是簡(jiǎn)單的調(diào)用了InvocationHandler的invoke方法,即可以對(duì)其進(jìn)行特殊的操作,也就是說(shuō)JDK的動(dòng)態(tài)代理還可以代理上述三個(gè)方法。
- 代理類(lèi)實(shí)現(xiàn)代理接口的sayHello方法中,只是簡(jiǎn)單的調(diào)用了InvocationHandler的invoke方法,我們可以在invoke方法中進(jìn)行一些特殊操作,甚至不調(diào)用實(shí)現(xiàn)的方法,直接返回。
Java設(shè)計(jì)模式

事務(wù)隔離級(jí)別
隔離級(jí)別是指若干個(gè)并發(fā)的事務(wù)之間的隔離程度。TransactionDefinition 接口中定義了五個(gè)表示隔離級(jí)別的常量:
- TransactionDefinition.ISOLATION_DEFAULT:這是默認(rèn)值,表示使用底層數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別。對(duì)大部分?jǐn)?shù)據(jù)庫(kù)而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級(jí)別表示一個(gè)事務(wù)可以讀取另一個(gè)事務(wù)修改但還沒(méi)有提交的數(shù)據(jù)。該級(jí)別不能防止臟讀和不可重復(fù)讀,因此很少使用該隔離級(jí)別。
- TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級(jí)別表示一個(gè)事務(wù)只能讀取另一個(gè)事務(wù)已經(jīng)提交的數(shù)據(jù)。該級(jí)別可以防止臟讀,這也是大多數(shù)情況下的推薦值。
- TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級(jí)別表示一個(gè)事務(wù)在整個(gè)過(guò)程中可以多次重復(fù)執(zhí)行某個(gè)查詢(xún),并且每次返回的記錄都相同。即使在多次查詢(xún)之間有新增的數(shù)據(jù)滿(mǎn)足該查詢(xún),這些新增的記錄也會(huì)被忽略。該級(jí)別可以防止臟讀和不可重復(fù)讀。
- TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事務(wù)依次逐個(gè)執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說(shuō),該級(jí)別可以防止臟讀、不可重復(fù)讀以及幻讀。但是這將嚴(yán)重影響程序的性能。通常情況下也不會(huì)用到該級(jí)別。
事務(wù)傳播行為
所謂事務(wù)的傳播行為是指,如果在開(kāi)始當(dāng)前事務(wù)之前,一個(gè)事務(wù)上下文已經(jīng)存在,此時(shí)有若干選項(xiàng)可以指定一個(gè)事務(wù)性方法的執(zhí)行行為。在TransactionDefinition定義中包括了如下幾個(gè)表示傳播行為的常量:
- TransactionDefinition.PROPAGATION_REQUIRED:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。
- TransactionDefinition.PROPAGATION_REQUIRES_NEW:創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
- TransactionDefinition.PROPAGATION_SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。
- TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
- TransactionDefinition.PROPAGATION_NEVER:以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。
- TransactionDefinition.PROPAGATION_MANDATORY:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù),則拋出異常。
- TransactionDefinition.PROPAGATION_NESTED:如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來(lái)運(yùn)行;如果當(dāng)前沒(méi)有事務(wù),則該取值等價(jià)于TransactionDefinition.PROPAGATION_REQUIRED。
這里需要指出的是,前面的六種事務(wù)傳播行為是 Spring 從 EJB 中引入的,他們共享相同的概念。而 PROPAGATION_NESTED是 Spring 所特有的。以 PROPAGATION_NESTED 啟動(dòng)的事務(wù)內(nèi)嵌于外部事務(wù)中(如果存在外部事務(wù)的話(huà)),此時(shí),內(nèi)嵌事務(wù)并不是一個(gè)獨(dú)立的事務(wù),它依賴(lài)于外部事務(wù)的存在,只有通過(guò)外部的事務(wù)提交,才能引起內(nèi)部事務(wù)的提交,嵌套的子事務(wù)不能單獨(dú)提交。如果熟悉 JDBC 中的保存點(diǎn)(SavePoint)的概念,那嵌套事務(wù)就很容易理解了,其實(shí)嵌套的子事務(wù)就是保存點(diǎn)的一個(gè)應(yīng)用,一個(gè)事務(wù)中可以包括多個(gè)保存點(diǎn),每一個(gè)嵌套子事務(wù)。另外,外部事務(wù)的回滾也會(huì)導(dǎo)致嵌套子事務(wù)的回滾。
JVM內(nèi)存管理
堆內(nèi)存、棧內(nèi)存溢出
中間件
HashMap原理
是基于Map接口的實(shí)現(xiàn),存儲(chǔ)鍵值對(duì)時(shí),它可以接收null的鍵值,是非同步的,HashMap存儲(chǔ)著Entry(hash, key, value, next)對(duì)象。
通過(guò)hash的方法,通過(guò)put和get存儲(chǔ)和獲取對(duì)象。存儲(chǔ)對(duì)象時(shí),我們將K/V傳給put方法時(shí),它調(diào)用hashCode計(jì)算hash從而得到bucket位置,進(jìn)一步存儲(chǔ),HashMap會(huì)根據(jù)當(dāng)前bucket的占用情況自動(dòng)調(diào)整容量(超過(guò)Load Facotr則resize為原來(lái)的2倍)。獲取對(duì)象時(shí),我們將K傳給get,它調(diào)用hashCode計(jì)算hash從而得到bucket位置,并進(jìn)一步調(diào)用equals()方法確定鍵值對(duì)。如果發(fā)生碰撞的時(shí)候,Hashmap通過(guò)鏈表將產(chǎn)生碰撞沖突的元素組織起來(lái),在Java 8中,如果一個(gè)bucket中碰撞沖突的元素超過(guò)某個(gè)限制(默認(rèn)是8),則使用紅黑樹(shù)來(lái)替換鏈表,從而提高速度。