文章目錄
- Java基礎
- 字符型常量和字串常量
- 多載和重寫的區別
- 成員變數與區域變數
- ==和equals()
- hashcode()和equals()
- transient關鍵字
- BIO、NIO和AIO
- Java集合
- ArrayList和LinkedList
- HashMap和HashTable
- HashMap底層實作
- comparable和comparator
- 小結
- Java多執行緒
- JVM

Java基礎
字符型常量和字串常量
- 字符常量時單引號引起的一個字符,字串常量時雙引號引起的若干字符,
- 字符常量相當于一個整型值,可以參加運算式運算,字串常量代表一個地址值,
- 字符常量只占2位元組,字串常量占若干位元組,
多載和重寫的區別
多載:是同樣的一個方法能夠根據輸入資料的不同,做出不同處理,多載是同一個類中多個同名方法根據不同的傳參執行不同的邏輯處理,
重寫:是當子類繼承自父類的相同方法,輸入資料一樣,但是要做出的和父類不一樣的回應時,就要重寫父類方法,重寫是子類堆父類的重新改造,外部樣子不能改變,但是可以改變內部邏輯,
以最常見的構造器為例,構造器不能被重寫(override),但是可以被多載(overload),也就是經常看見一個類中有很多構造器的情況,
成員變數與區域變數
- 語法形式上,成員變數是屬于類的,而區域變數是方法中定義的變數或是方法的引數,成員變數可以被
static、private、public等修飾符修飾,而區域變數是不能被訪問修飾符鎖修飾的,但是他們都可以被final關鍵字修飾, - 存盤方式上,成員變數如果是使用
static關鍵字修飾的,那么這個成員變數就是屬于類的,反之是屬于實體的,物件存于堆記憶體,如果區域變數型別為基本資料型別,那么存盤在堆疊記憶體,如果為參考資料型別,那存放的是指向堆記憶體物件的參考或是指向常量池中的地址, - 生存時間上,成員變數是物件的一部分,它隨著物件的創建而存在,而區域變數隨著方法的呼叫的自動創建和消失,
- 成員變數如果沒有賦初始值的話,會自動以型別的默認值而復制;而區域變數則不會自動賦值,
==和equals()
==:判斷兩個物件的記憶體地址是不是相等,
equals():判斷兩個物件是不是同一個物件,
- 當類沒有覆寫
equals()方法時,則通過equals()比較的是該類的兩個物件,這種情況等價于==, - 當類有覆寫
equals()方法時,一般我們會通過比較兩個物件的內容來判斷是否相等,
public class Car {
public static void main(String[] args) {
String a="一鍵三連";//常量池中
String b="一鍵三連";
String c=new String("一鍵三連");//參考
String d=new String("一鍵三連");
System.out.println(a==b);//true,指向常量池同一個地址
System.out.println(c==d);//false,兩個不同的參考地址
System.out.println(a.equals(b));//true,判斷內容
System.out.println(c.equals(d));//true
}
}
注意:
String中的equals()方法是被重寫過的,因為object中的equals()方法比較的是物件的記憶體地址,而String中的equals()方法是比較物件的值,- 當創建
String型別的物件時,虛擬機會再常量池中查找是否有已存在的值相同物件,若有則把它賦給當前參考,沒有的話則重新創建一個,
hashcode()和equals()
你知道為什么重寫equals()方法必須重寫hashcode()方法嗎?
先介紹下hashcode:hashcode()的作用是獲取一個int整數即哈希碼,也稱為散列碼,哈希碼是確定物件在哈希表中的索引位置,Java中的所有類都包含該函式,
哈希碼在HashSet中應用:當把物件加入HashSet時,HashSet會先計算物件的hashcode來判斷物件加入的位置,同時也會與該位置其他加入物件的hashcode作比較,若沒有相符的hashcode則會假設物件沒有重復出現,否則會呼叫equals()方法來檢查哈希碼相同的物件內容是否相同,若內容也相同,HashSet就不會讓其成功加入;否則的話就會重寫散列到其他位置,通過hashcode大大減少了equals的呼叫次數,提高執行效率,這也回答了開頭的問題,
hashcode()和equals()相關規定:
- 若兩個物件相等,則
hashcode一定是相同的,呼叫equals()也都是回傳true - 兩個物件有相同的
hashcode,但它們不一定相等 - 因此
equals()覆寫的地方,hashcode()方法也必須覆寫, hashcode()默認是對堆上的物件產生獨特值,如果沒有重寫hashcode(),則該class的兩個物件無論如何都不會相等,
transient關鍵字
對于不想進行序列化的變數,使用transient關鍵字修飾,當物件被反序列化時,被transient關鍵字修飾的變數值不會被持久化和恢復,transient只能修飾變數,不能修飾方法和類,
BIO、NIO和AIO
- BIO(Blocking I/O,同步阻塞I/O模式),資料的讀取寫入必須阻塞在一個執行緒內等待其完成,讓每個連接專注于自己的I/O并且編程模式簡單,不用過多考慮系統加載、限流等問題,但是連接數非常大時就無能為力了,
- NIO(Non-blocking/New I/O,同步非阻塞I/O模式),支持面向緩沖的,基于通道的I/O操作方法,阻塞模式使用就像傳統中的支持一樣,較為簡單,但是性能和可靠性不好,而非阻塞模式正好與之相反,對于高負載、高并發的應用程式,應使用NIO模式開發,
- AIO(Asynchronous I/O,異步非阻塞模式),異步I/O是基于回呼機制實作的,也就是應用操作之后會直接回傳,而不是阻塞在那里,當后臺處理完成后,作業系統會通知相應的執行緒進行后續的操作,
Java集合
ArrayList和LinkedList
- 執行緒安全
ArrayList和LinkedList都是不同步的,也就是執行緒不安全,vector是同步的,執行緒安全, - 底層資料結構
ArrayList底層使用的是Object陣列,LinkedList底層使用的是雙向鏈表, - 插入和洗掉元素
ArrayList采用陣列存盤,所以插入和洗掉受元素位置影響;LinkedList采用鏈表存盤,所以插入和洗掉元素時受到元素位置影響, - 快速隨機訪問
快速隨機訪問是通過元素的序號快速獲取元素物件,通過底層資料就夠就知道了,ArrayList支持,LinkedList不支持, - 記憶體空間占用
ArrayList的空間主要浪費在了list串列的結尾會預留一定的容量空間,而LinkedList主要花費在每一個元素都要比ArrayList更多的空間,因為存前驅后繼節點及資料等,
HashMap和HashTable
- 執行緒安全
HashMap是執行緒不安全的,而HashTable是執行緒安全的,因為HashTable的內部實作都加了synchronized修飾, - 效率
因為上述執行緒安全的問題,HashMap效率也就更高一點, - Null
HashMap中可以把null作為鍵或值,而HashTable不支持, - 擴容
若創建時未指定容量,HashMap初始為 16 16 16,每次擴容為2倍,HashTable初始為 11 11 11,并且每次擴容為 2 n + 1 2n+1 2n+1,
若創建時指定了容量,HashMap會將其擴充至 2 2 2的冪次方大小,HashTable會直接使用給定的容量, - 底層資料結構
HashMapjdk1.8以后,當鏈表長度超過閾值(默認8)時,會轉換為紅黑樹,以減少搜索時間,而HashTable沒有這樣的機制,
(
插播反爬資訊)博主CSDN地址:https://wzlodq.blog.csdn.net/
HashMap的長度為什么是2的冪次方?
為了能讓HashMap減少碰撞高效存盤,要盡量把資料分配均勻,首先哈希值的取值范圍很大,有將近40億的空間,記憶體時放不下的,換言之,哈希值并不能直接使用,需要對陣列的長度進行取模,得到的余數就是對應的陣列下標,
而設計成2的冪次就是因為如果取余操作中除數是2的冪次的話,就等價于與其除數減一的與操作,也就是說
h
a
s
h
%
l
e
n
g
t
h
=
(
l
e
n
g
t
h
?
1
)
&
h
a
s
h
hash\%length=(length-1)\&hash
hash%length=(length?1)&hash,而采用二進制位運算可以大大提高效率,這也就是為什么HashMap的長度是2的冪次方,
HashMap底層實作
JDK1.8之前:
JDK1.8之前HashMap底層是陣列和鏈表結合在一起使用也就是鏈表散列,HashMap通過key的hashcode經過擾動函式處理后得到hash值,然后通過
(
n
?
1
)
&
h
a
s
h
(n-1)\&hash
(n?1)&hash判斷當前元素存放的位置,如果當前位置存在元素的話,就判斷該元素與要存入的元素的hash值以及是否相同,若相同則直接覆寫,否則通過拉鏈法來解決沖突,所謂擾動函式指的就是HashMap的hash方法,使用hash方法之后可以減少碰撞,

JDK1.8之后:
優化了哈希沖突的解決方法,當鏈表長度大于閾值(默認為8)時,會將鏈表轉換為紅黑樹,以減少搜索時間,

comparable和comparator
comparable介面出自java.lang包,它有一個compateTo(Object obj)方法用來排序,comparator介面出自java.util包,他有一個compare(Object obj1,Object obj2)方法用來排序,
public static void main(String[] args) {
ArrayList<Integer> l = new ArrayList();
l.add(2);
l.add(1);
l.add(3);
System.out.println("===原始===");
System.out.println(l);
System.out.println("===自然排序===");
Collections.sort(l);
System.out.println(l);
System.out.println("===定制排序===");
Collections.sort(l, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
System.out.println(l);
}
/*運行結果如下:
===原始===
[2, 1, 3]
===自然排序===
[1, 2, 3]
===定制排序===
[3, 2, 1]
*/
public class Car implements Comparable<Car>{
private String name;
private double price;
public Car(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
@Override
public int compareTo(Car o) {
if(this.price==o.getPrice()) //價格相同 名字升序
return this.name.compareTo(o.getName());
else if(this.price>o.getPrice())return -1;
else return 1; //價格降序
}
public static void main(String[] args) {
ArrayList<Car> l =new ArrayList();
l.add(new Car("C",10));
l.add(new Car("A",10));
l.add(new Car("C",15));
Collections.sort(l);
System.out.println(l);
}
}
/*運行結果如下:
[Car{name='C', price=15.0}, Car{name='A', price=10.0}, Car{name='C', price=10.0}]
*/
小結
Collection
- List
①ArrayList:Object陣列
②Vector:Object陣列
③LinkedList:雙向鏈表 - Set
①HashSet:無序唯一,底層采用HashMap保存元素
②TreeSet:有序唯一,紅黑樹(即自平衡的排序二叉樹)
Map
- HashMap:jdk1.8前時陣列+鏈表,jdk1.8后大于閾值(默認8)則轉鏈表為紅黑樹
- LinkedHashMap:繼承自HashMap,增加了雙向鏈表
- HashTable:陣列+鏈表
- TreeMap:紅黑樹
Java多執行緒
Java多執行緒面試題-可能學了個寂寞?
JVM
還不會JVM,是準備家里蹲嗎?
原創不易,請勿轉載(
本不富裕的訪問量雪上加霜)
博主首頁:https://wzlodq.blog.csdn.net/
微信公眾號:唔仄lo咚鏘
如果文章對你有幫助,記得一鍵三連?
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/271326.html
標籤:java
上一篇:友元和static
