目標
靜態/動態,可變/不變,Snapshot圖,集合類,NULL
資料型別
基本資料型別
沒啥好說的
物件資料型別
String,Integer等
區別
Boxed primitives
將基本型別包裝為物件型別,但不常用,通常是為了集合類而用
層次結構
物件結構有extends(繼承)等關係
操作
既可以是普通的運算子,也可以是Object物件的方法或函式,比如bigint1.add(bigint2)
add()是一個方法
Static vs. dynamic data type checking
型別檢查
檢查資料型別和值是否符合
- 靜態型別在編譯階段進行型別檢查
- 動態型別在執行階段進行型別檢查
注意,類似如下的東西會報錯,需要轉換:
String five = 5; // ERROR!
ERROR:
test.java.2: incompatible types
found: int
required: java.lang.String
String five = 5;
靜態型別檢查
👍靜態型別檢查在編譯階段就發現錯誤,避免將bug帶入執行階段,提高正確性健壯性
❓檢查些啥
- 語法錯誤
- 類名錯誤
- 引數數量
- 引數型別
- 返回值型別
動態型別檢查
動態型別在執行階段,才能根據當前確定的值進行檢查,其錯誤由Exception給出
❓檢查些啥
- 非法引數值
- 非法返回值
- 越界index
- 空指標
可變/不可變資料
❓首先,賦值的本質:在記憶體特定區域開闢一段空間,寫入特定值,再將該空間與變數(引用)關聯到一起(即先寫值,再講變數與記憶體關聯起來)
改變的問題
- 改變一個變數:將變數指向另一個值的儲存空間,本質是更改了關聯
String a = “abc”; a = “def”;
- 改變一個變數的值:將儲存空間中的值重新寫入
Date a = new Date(2024, 1, 1); a.setMonth(2);
我們儘量避免變化,以免帶來問題
Immutability
一種重要的設計原則:不變性
不變資料型別:一旦被建立,其值不能改變
🌰例子:其實最終,a對應的值是變成def了,但我們所說的不變是,“abc”在記憶體中的值不變化。只是把a指向def了
不同的是StringBuilder,他可以修改記憶體空間裡的值
❓有什麼區別?值不是一樣嗎?有多個變數引用同一個記憶體空間的時候,會出現不同:
優劣
不可變型別雖然保證安全和設計,但對其頻繁修改會產生大量的臨時複製(需要垃圾回收)
可變型別:
- 最少化複製以提高效率
- 使用可變資料型別,可獲得更好的效能
- 適合於在多個模組之間共享資料
final
😀所以引入final,不能改變指向關係。如果這是不變資料型別,則新增final的欄位的值更改會報錯。
因此,儘量使用final來作為方法的輸入引數和區域性變數,表明了這個值不會被更改
📕final類無法派生子類,final變數不能改變值和引用(引用就是關聯),final的方法不能被子類重寫
final與Immutability的區別
不變物件:指向值不能被修改
可變物件:有方法時可以修改指向的值
不變引用:變數與記憶體空間的關聯關係不可修改
可變引用:可以修改
安全性:
當採用可變型別時(本例子為List),myData傳入sumAbsolute()
時被改變,因此導致兩個輸出值一樣
這種錯誤難以追蹤,難以理解。
😀因此,只在區域性變數,不涉及共享,且只有一個引用的時候使用可變型別
防禦式複製
將可變型別複製到一個新物件中,返回給客戶端
return new Date(end.getTime())
等
Snapshot
描述程式執行時的內部狀態,解釋設計思路
基本型別
物件型別
不可變物件,用雙線橢圓
不可變引用final,用雙線箭頭
例子:沒有final,因此s2=s1.concat 指向了abcde
複雜資料型別:集合、陣列、連結串列
只能用於Object
陣列和連結串列不用說,但迭代器可以說
//array
int max = 0;
for (int i=0; i<array.length; i++) {
max = Math.max(array[i], max);
}
//list
int max = 0;
for (int x : list) {
max = Math.max(x, max);
}
Set集合
無序的,但同一個object不能重複出現。
Map詞典
key唯一,值可以重複,也是無序
Set和Map同樣使用迭代器進行迭代
List<String> cities
= new ArrayList<>();
Set<Integer> numbers
= new HashSet<>();
Map<String,Turtle> turtles
= new HashMap<>();
for (String city : cities) {
System.out.println(city);
}
for (int num : numbers) {
System.out.println(num);
}
for (int ii = 0; ii < cities.size(); ii++) {
System.out.println(cities.get(ii));
}
for (String key : turtles.keySet()) {
System.out.println(key + ": " + turtles.get(key));
}
迭代器可能產生破壞