基礎(chǔ)
1, static 關(guān)鍵字 表明在沒有所屬類的實例變量的情況下被訪問。
static方法就是沒有this的方法。在static方法內(nèi)部不能調(diào)用非靜態(tài)方法。
靜態(tài)變量被所有的對象所共享,在內(nèi)存中只有一個副本,它只在類初次加載時會被初始
不能被覆蓋。
2, 覆蓋方法是基于運行時動態(tài)綁定的,static 是編譯時靜態(tài)綁定的。
3, java 運行時環(huán)境(jre),包括java虛擬機,java核心類庫和支持文件
4, java 開發(fā)工具(jdk) , 完整的java軟件包, 包含jre, 編譯器, 其他工具javaDoc, 調(diào)試器等
序列化
序列化就是把對象轉(zhuǎn)化為0和1二進(jìn)制編碼,有兩個作用1.用于網(wǎng)絡(luò)傳輸。2.可以存儲到硬盤中,用來保存。
使用場景:所有可在網(wǎng)絡(luò)上傳輸?shù)膶ο蠖急仨毷强尚蛄谢?,比如RMI(remote method invoke,即遠(yuǎn)程方法調(diào)用),傳入的參數(shù)或返回的對象都是可序列化的,否則會出錯;
所有需要保存到磁盤的java對象都必須是可序列化的。
對象相等
equals
Object類中的equals方法和“==”是一樣的,沒有區(qū)別,即倆個對象的比較是比較他們的棧內(nèi)存中存儲的內(nèi)存地址。
當(dāng)需要判斷對象是否相等時(如對象作map的key,唯一),需重寫equals
如果不重寫equals()方法,相同的內(nèi)容不同引用的對象會被當(dāng)做不同的對象被使用
重寫equals方法的要求:
1、自反性:對于任何非空引用x,x.equals(x)應(yīng)該返回true。
2、對稱性:對于任何引用x和y,如果x.equals(y)返回true,那么y.equals(x)也應(yīng)該返回true。
3、傳遞性:對于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也應(yīng)該返回true。
4、一致性:如果x和y引用的對象沒有發(fā)生變化,那么反復(fù)調(diào)用x.equals(y)應(yīng)該返回同樣的結(jié)果。
5、非空性:對于任意非空引用x,x.equals(null)應(yīng)該返回false。
注意:1、重寫equals必須重寫hashCode方法 ?因為是先比較兩個對象的hash值是否相等在判斷值 ????????
2、equals() 和 hashCode() 的定義必須兼容 如果 x.equals(y) 則x , y 的hashCode必須相等,
3、x , y 的 hashCode相等,x , y 不一定相等
hashCode
什么是哈希碼?就是一套算法算出來的一個值,且這個值對于這個對象相對唯一。在Java應(yīng)用程序執(zhí)行期間,在對同一對象(未修改)多次調(diào)用 hashCode 方法時,必須一致地返回相同的整數(shù)。
1如果散列表中存在和散列原始輸入K相等的記錄,那么K必定在f(K)的存儲位置上
2不同關(guān)鍵字經(jīng)過散列算法變換后可能得到同一個散列地址,這種現(xiàn)象稱為碰撞
3如果兩個Hash值不同(前提是同一Hash算法),那么這兩個Hash值對應(yīng)的原始輸入必定不同
可以理解為K多對一 Hash,因為f(K)不會有倆個計算結(jié)果hash, 而有可能f(K1)=f(K2)=Hash
hashCode的作用,用來查找 對象在內(nèi)存中的位置。 如 把K的hashCode % 9,算出的結(jié)果則為內(nèi)存的結(jié)果,有數(shù)據(jù)了則取決于算法去加1或者鏈表。
查找的時候,對比對象是否相同時候,則先對比hashCode,如果不同則不同,相同則在對比equals。
String就是一個對象,本質(zhì)是個char[] ,自己重寫了equals和hashCode, 遍歷char數(shù)組中的每個字符來實現(xiàn)equals和hashCode。
public int hashCode() {
????????int h = hash;
????????if (h == 0 && value.length > 0) {
????????????char val[] = value;
????????????for (int i = 0; i < value.length; i++) {
????????????????h = 31 * h + val[i];
????????????}
????????????hash = h;
????????}
????????return h;
}
使用String的 char 數(shù)組的數(shù)字每次乘以 31 再疊加最后返回,因此,每個不同的字符串,返回的 hashCode 肯定不一樣。
在名著《Effective Java》第 42 頁就有對 hashCode 為什么采用 31 做了說明:
之所以使用31, 是因為他是一個奇素數(shù)。如果乘數(shù)是偶數(shù),并且乘法溢出的話,信息就會丟失,因為與2相乘等價于移位運算(低位補0)。使用素數(shù)的好處并不很明顯,但是習(xí)慣上使用素數(shù)來計算散列結(jié)果。 31 有個很好的性能,即用移位和減法來代替乘法,可以得到更好的性能: 31 * i == (i << 5) - i, 現(xiàn)代的 VM 可以自動完成這種優(yōu)化。這個公式可以很簡單的推導(dǎo)出來。
集合
Collection
├List (有序集合,允許相同元素和null)
│├LinkedList (非同步,允許相同元素和null,遍歷效率低插入和刪除效率高)
│├ArrayList (非同步,允許相同元素和null,實現(xiàn)了動態(tài)大小的數(shù)組,遍歷效率高,用的多)
│└Vector(同步,允許相同元素和null,效率低)
│ └Stack(繼承自Vector,實現(xiàn)一個后進(jìn)先出的堆棧)
└Set (無序集合,不允許相同元素,最多有一個null元素)
?????|-HashSet(無序集合,不允許相同元素,最多有一個null元素)
Map (沒有實現(xiàn)collection接口,key不能重復(fù),value可以重復(fù),一個key映射一個value)
├Hashtable (實現(xiàn)Map接口,同步,不允許null作為key和value,用自定義的類當(dāng)作key的話要復(fù)寫hashCode和eques方法,)
├HashMap (實現(xiàn)Map接口,非同步,允許null作為key和value,用的多)
└WeakHashMap(實現(xiàn)Map接口)
泛型的定義:在程序中我們將一個對象放入集合中,但是集合不會記住對象的類型,當(dāng)我們在次使用對象的時候,對象變?yōu)镺bject類型,而程序中還是原來的類型,我們必須要自己轉(zhuǎn)換其類型,為了解決這個問題,則提出泛型。
Java中數(shù)組是對象,父類是Object,每個數(shù)組都實現(xiàn)了接口Cloneable and java.io.Serializable
有自己的類名,如int[]的類名是 [I
Arrays
Arrays類位于 java.util 包中,主要包含了操縱數(shù)組的各種方法, 有搜索,排序,填充,復(fù)制等。
Arrays.asList(T… data)
注意:該方法返回的是Arrays內(nèi)部靜態(tài)類ArrayList,而不是我們平常使用的ArrayList,,該靜態(tài)類ArrayList沒有覆蓋父類的add, remove等方法,如果直接調(diào)用,會報異常。
hashMap
Key常用String ,string已經(jīng)重寫了hashCode
HashMap中定位到桶的位置 是根據(jù)Key的hash值與數(shù)組的長度取模來計算的。getNode() 方法中
p = tab[i = (n - 1) & hash]?
可以理解為,將hash的 bit 位截取到 (n - 1) 的 bit 位長度。并找到該字節(jié)對映的 node 數(shù)組坐標(biāo)中的值。所以數(shù)組的長度都要為2^n。

hash方法:return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
可以看成是hashCode高位 和 地位 的異或計算得到的hash值。
可以真正的動一位則動全身。不論高位還是低位,只要有一位不同,計算存儲位置相同的概率就會大幅度降低(但是還是有的)。
