關注公衆號【愛做夢的錘子】後臺回覆【java知識點】可下載整理好的xmind思維導圖
基礎知識
基本數據類型
8種基本數據類型
-
字符型
- char-1
-
布爾型
- boolean-1
-
數值(符號位,一個字節=8位)
-
byte-1
-
short-2
-
int-4
-
long-8
-
float-4
-
double-8
-
浮點型
- 一種對實數的近似值的表現法,由一個有效數字加上冪數來表示,
自動拆裝箱
自帶拆裝箱
-
基本數據類型
- 不需要new,在棧內存存儲,比較高效
-
包裝類型
- 基本數據類型不是面向對象的,Java語言在設計時,添加基本數據類型對應的包裝類型
-
裝箱
- 基本數據類型->包裝類型【通過Integer.valueOf() 以int爲例】
-
拆箱
- 包裝類型->基本數據類型 【通過integer.intValue 以Integer爲例】
-
Java5開始提供自動拆裝箱
-
缺點
-
包裝對象的數值比較不能簡單的使用==
-
自動拆箱時會可能引發NPE
-
for循環中如果存在大量的拆裝箱,會浪費資源
-
緩存機制
-
Integer的緩存機制
-
Java5新增功能,節省內存,提高性能
-
整型對象通過使用相同的對象引用實現了緩存和重用
-
整數區間在-128-127之間數值適用,最大值127可以通過-XX:AutoBoxCacheMax=size修改
自動裝箱適用
-
其他緩存(通過包裝成a,b兩個對象時,可以使用a==b判斷其是否相等)
-
-128至127之間的整數(§3.10.1)
-
true 和 false的布爾值 (§3.10.3)
-
‘\u0000’至 ‘\u007f’之間的字符(§3.10.4)
-
Byte, Short, Long有固定範圍: -128 到 127。對於Character, 範圍是 0 到 127。除了Integer以外,這個範圍都不能改變。
-
String
不可變性
- 一個String對象在內存堆中被創建出來,他就無法被修改
Java6與Java7的substring
- java6,導致問題:在一個很長的字符串中截取較短的一部分,會導致這個較長的字符串不能被回收,致使內存泄露,已被官方標記爲JDK6的BUG
//JDK 6
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
public String substring(int beginIndex, int endIndex) {
//check boundary
return new String(offset + beginIndex, endIndex - beginIndex, value);
}
- java7
//JDK 7
public String(char value[], int offset, int count) {
//check boundary
this.value = Arrays.copyOfRange(value, offset, offset + count);
}
public String substring(int beginIndex, int endIndex) {
//check boundary
int subLen = endIndex - beginIndex;
return new String(value, beginIndex, subLen);
}
replaceFirst、replaceAll、replace區別
-
replaceFirst:基於正則表達式的匹配替換,只替換匹配到的第一個
-
replaceAll:基於正則表達式的匹配替換,替換全部符合規則的字符和字符串
-
replace:可以支持字符的替換,也支持字符串的替換,替換全部匹配的字符和字符串
字符串的拼接
-
concat拼接
- 生成一個新的字符串
-
+ 拼接
- 語法糖,實際上還是使用的時StringBuilder的append方法
-
StringBuffer
- 線程安全,append方法使用synchronized 修飾
-
StringBuilder
-
Java8中String.join方法
-
5中方式拼接相同字符串,耗時
- StringBuilder<StringBuffer<concat<+<StringUtils.join
String.valueOf和Integer.toString的區別
- 無區別,String.valueOf是通過調用Integer.toString實現
switch支持
-
java7開始switch支持String
-
switch支持int,直接通過比較int的值
-
switch支持char,將char字符轉換成對應的asii碼的數值,再進行比較
-
switch支持String,使用String的hashCode,以及equals方法來匹配
String str = "world";
String s;
switch((s = str).hashCode())
{
default:
break;
case 99162322:
if(s.equals("hello"))
System.out.println("hello");
break;
case 113318802:
if(s.equals("world"))
System.out.println("world");
break;
}
字符串池
-
字符串池是由String類私有的維護,是爲了提升性能和減少內存開銷,避免字符串的重複創建
-
字符串創建方式
-
直接使用字符串賦值。直接去字符串池中查找當前字符串值是否存在,存在,則直接將池中引用返回;如果不存在,則在字符串池中創建對象,然後將池中引用返回
-
顯式new String()。首先會去字符串池中查找當前字符串值是否存在,如果不存在,則在字符串池中創建對象,存在則不創建。最後還要在堆中額外創建一個字符串對象,最後是將堆中對象的引用返回
-
-
回收機制
- new關鍵字創建的字符串對象如果不可達就會被gc回收。而字符串字面量創建的字符串對象,因爲常量池中還持有對該字符串的引用,則不會被回收。這並不代表字符串池中的字符串永遠不被回收,字符串池提供有GC相關接口,根據不同的GC策略,會在適當的時候回收
常量池
-
運行時常量池
-
屬於方法區的一部分
-
Java並不要求常量都必須在編譯期產生,運行期也可以產生新的常量,這些新的常量就被放在運行時常量池中
-
-
class常量池
- class文件結構
class文件最前的四個字節,用於存儲Magic Number,來確定這個class文件是否能夠被這個虛擬機所接受。接下來的4個字節用來存儲版本號,前兩個字節存儲次版本號,後兩個字節存儲主版本號。在這之後就是常量池的入口,開始的兩個字節爲常量池容量計數器,記錄常量池中常量數量
* class常量池是class文件的資源倉庫
字面量:Java語言層面常量的概念,如文本字符串,聲明爲final的常量值
符號引用量: 類和接口的 全限定 名、 字段名稱和描述符、方法名稱和描述符
intern
-
intern() 方法返回字符串對象的規範化表示形式
-
”string”.intern()方法的時候會返回”string”,但是這個方法會首先檢查字符串池中是否有”string”這個字符串,如果存在則返回這個字符串的引用,否則就將這個字符串添加到字符串池中,然會返回這個字符串的引用
Java關鍵字
transient
-
表示變量不被序列化處理
-
序列化
- 序列化即對一個對象進行持久化處理,將對象轉換成字節流進行存儲和傳輸
-
反序列化
- 將一個序列化後的對象字節流轉換成其對應對象是反序列化
instanceof
-
Java中的一個雙目運算符,用來測試一個對象是否是屬於某一個類的實例
-
當該對象是屬於該類創建的實例時返回 true
-
當該對象不屬於該類所創建的實例時返回 false
-
volatile
-
可見性
- 可見性,是指線程之間的可見性,一個線程修改的狀態對另一個線程是可見的。
-
問題
- 在多線程操作同一個變量時,實際上是在每個線程中開啓一塊緩存,將該變量的值複製一份,緩存在當前線程緩存中,這就無法確保執行讀操作的線程能實時地看到其他線程寫入的值
-
作用
- 被volatile修飾的變量,當一個線程修改了這個變量的值,volatile 保證了新值能立即同步到主內存,且各個線程每次使用前都立即從主內存刷新,即可實時看到其他線程實時更新值
synchronized
-
同步方法或同步代碼塊
-
synchronized取得的鎖都是對象鎖,synchronized塊之間具有互斥性,支持重入,不保證公平性,等待線程採用競爭方式獲取鎖,發生異常時會自動釋放鎖
final
-
修飾類
-
該類不能被繼承
-
類中成員變量,可以自行設置是否爲final
-
類中成員方法隱式爲final
-
-
修飾方法
- 該方法不能被重寫
-
修飾變量
-
必須初始化
-
初始化後不可更改
-
static
-
修飾內部類
- 內部類可直接通過外部類的類名調用,不用需要創建外部類實例來調用
-
修飾方法
- 該方法從屬於該類,可以使用類名之間調用
-
修飾變量
- 靜態變量,屬於該類
-
修飾代碼塊
- 類被加載時,該代碼塊會被執行一次
const
- const是java中的預留關鍵字