03_Java 基礎_常用類
程式碼塊
在類或方法中,使用 {} 括起來的一段程式碼,稱之為程式碼塊。
- 區域性程式碼塊,定義在方法內部,呼叫方法時執行
- 初始化程式碼塊,定義在類中,每建立一個物件,就會執行一次,編譯時,會把初始化程式碼塊放入構造器中
- 靜態程式碼塊,在初始化程式碼塊前加 static,載入位元組碼時自動呼叫,只執行一次
執行程式碼時,會把工程中所有的 Java 檔案編譯成位元組碼,放到 classPath 中,當第一次使用到該類時,就把該類物件的位元組碼載入到 JVM 中
final 關鍵字
繼承的弊端:破壞了我們的封裝,它可以訪問父類中實現的細節,可以覆蓋父類中的方法。
使用 final 關鍵字修飾,表示最終的,不可修改的,保證資料安全
- 修飾字段,不能修改,常量,必須給初始值,修飾基本資料型別表示值不能改變,修飾引用資料型別表示地址不能改變
- 修飾方法,不能覆蓋
- 修飾類,不能繼承
包裝類
對基本資料型別的包裝,把基本資料型別包裝成一個類,以面向物件的思想使用包裝類,使基本資料型別更強大。
基本資料型別 | 包裝類 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
裝箱操作
把基本資料型別變成包裝類。
- 使用 new 方式
- 使用 Integer.valueOf() 方式(先找快取)
拆箱操作
把包裝類的物件,轉換為對應基本資料型別的變數
- int num1 = num.intValue();
自動裝箱(語法糖)
可以直接把基本資料型別的值賦給包裝類物件
- Integer i = 10;
自動拆箱(語法糖)
自動把包裝類物件轉換成基本資料型別
- int i1 = i;
基本資料型別和包裝類
-
預設值
int------------------0
Integer-----------null
-
包裝類當中提供了很多方法供我們直接使用
-
集合框架不能存放基本資料型別(陣列可以),只能存物件
使用場景:
- 欄位使用包裝型別(存放到堆)
- 方法當中使用基本資料型別(存放到棧)
包裝類當中的快取設計
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
抽象方法
只定義,不實現,子類必須覆蓋。
在方法前面加一個關鍵字 abstract
特點:
- 沒有方法體
- 必須定義在抽象類或者介面當中
- 不能是私有的 private,不能使用 final 修飾,也不能使用 static 修飾
抽象類
- 抽象類一般作為父類,必須要有子類實現。其實是一個不完整類。
- 抽象類不能直接建立物件
- 抽象類當中可以有抽象方法,也可以有非抽象方法(給子類用)
- 子類沒有覆蓋,把子類也變成抽象方法
- 構造方法不能定義成私有的 private,不能使用 final 修飾
命名:一般在前面加個 Abstract
介面
在 Java 中,介面表示一種規範、約束,要求實現者必須遵循該規範。用來約束使用者應該怎麼做,規範和實現相分離。
介面是一個特殊的抽象類。
介面的定義:interface 介面名稱
- 介面沒有構造方法,不能建立物件類
- 介面當中定義的變數,都是全域性靜態常量
- 介面當中定義的方法,都是公共的,抽象的方法
- 介面當中定義的內部類,都是公共的,抽象的類
- 介面可以多繼承
介面和抽象類的區別
- 都是被其他類繼承或實現
- 都不能例項化
- 都可以定義抽象方法,子類必須覆蓋
- 介面沒有構造器,抽象類有
- 介面只能包含抽象方法,抽象類可以包含普通方法和抽象方法
- 介面當中成員變數 public static final,抽象類當中成員變數預設許可權
- 介面當中方法 public abstract,抽象類當中方法預設許可權
面向介面程式設計
把實現類物件賦值給介面型別的變數
多型的好處:遮蔽了不同類之間的實現差異,達到通用程式設計
內部類
定義在類當中的類
- 增強封裝
- 增強程式碼維護性
- 內部類可以直接訪問外部類成員
例項內部類
無修飾符,屬於物件,不屬於類
Outter.Inner in = out.new Inner();
外部類不能訪問內部類成員
例項內部類中有一個外部類引用,Outter.this
靜態內部類
static 修飾,屬於類,不需要建立物件
Outter.Inner in = new Outter.Inner();
靜態內部類中可以訪問外部類的靜態成員,但是沒有外部類引用
區域性內部類
定義在方法當中,不能使用修飾符,只能在定義的方法中使用,不能包含靜態變數
匿名內部類
區域性內部類的一種特殊情況,就是沒有名字的內部類,也沒有構造器,直接建立物件,只使用一次,內部方法直接執行
new 父類構造器 或 介面(){}
列舉
表示一個事物固定的狀態。是一個特殊的類,多個常量物件的集合。
- 資料安全
- 邏輯合理
[修飾符] enum 列舉名稱 {}
- 列舉不能直接建立物件,私有化構造器
- 列舉可用在 switch 中,呼叫 ordinal 序數
- 字串轉列舉型別,web 應用中常用
常用類
Main 方法
點選執行時,JVM 會呼叫 main 方法
- public:JVM 呼叫的方法,許可權要足夠大
- static:Jvm 呼叫的方法,不需要建立物件,直接使用類名呼叫
- void:Jvm 呼叫的方法,不需要任何返回值
- main:方法名稱,必須是這個,不然 JVM 識別不了
- String[] args:以前是指鍵盤錄入
Scanner
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
System
java.lang 包是不需要匯入的
- System.ArrayCopy 複製陣列
- System.currentTimeMillis 返回當前時間的毫秒值,從1970年到現在,做測試用,測試程式執行時間
- System.exit 終止當前正在執行的 Java 虛擬機器
- System.gc 立即執行垃圾回收器
- finalize:當一個類被回收時呼叫此方法
Math
- Math.random 返回一個 [0,1) 之間的隨機數
- Math.max 返回兩個數中的最大值
- Math.min 返回兩個數中的最小值
- Math.sqrt 開根
BigDecimal
- 無法準確表示高精度小數計算,尤其是金額,詳細請看 Java 基礎第一篇
- 通常使用 String 構造器,完全可預知的
- BigInteger 比 Long 還大的整型
String
本質是 char 型別的一個數組
- 不可變字串,定義好不能改變,修改就會建立新的地址
- String
- String str = "mystr"; 是個常量物件,存在方法區中的常量池,建立一個物件或不建立
- String str = new String("mystr"); 是個物件,在堆中開闢空間,引向常量池,至少建立一個物件
- String str = null; 引用為空,沒有初始化,沒有分配記憶體空間
- String str = ""; 字串為空,分配了記憶體空間,內容為空
- == 比較記憶體地址是否相等
- equals Object 中定義,與 == 相同,String 中覆蓋,比較內容是否相等
- String
- 可變字串,定義好可以改變,修改不會建立新的地址
- StringBuilder:效率高一些
- StringBuffer:方法前多了 synchronized,加鎖,安全一些
- 都實現了 CharSequence 介面
- char 型別陣列可以與 String 相互轉換
- 返回字串長度,length
- 獲取字串中的某個元素,charAt
- 返回一個子字串,subString
- 返回子字串在字串中第一次出現的位置,indexOf
- 返回子字串在字串中最後一次出現的位置,lastIndexOf
- 大小寫轉換,toLowerCast,toUpperCast
- 忽略大小寫比較,equalsIgnoreCase
- 以某一個字元對字串進行分割,split,返回字串陣列
- 判斷開頭,startsWith
- 去掉首尾空格,trim
- 去掉全部空格,使用 reqlace
Random
- new Random();
- new Random(seed); 相同的種子生成的隨機數是一樣的
- UUID:通用唯一識別符,結合當前時間和電腦硬體資訊生成一段字元。UUID.RandomUUID(),生成十六進位制
日期 Date
比如生日,入職時間等欄位 new Date();
日期格式化:
DateFormat.getInstance
DateFormat.getDateTimeInstance
df.format(); 日期轉字串
df.parse(); 字串轉日期
自定義日期模式:SimpleDateFormat
Date date = new Date();
SimpleDateFormat sd = new SimpleDateFormat();
String pattern = "yyyy/MM/dd HH:mm:ss";
sd.applyPattern(pattern);
System.out.println(sd.format(date));
集合
用來存放資料的一個容器
陣列和集合類的區別:
- 陣列當中可以存基本資料型別和引用型別
- 集合當中只能存放物件(引用型別),放基本資料型別也會自動裝箱
- 陣列長度固定,集合長度隨著元素增加而增加
- 如果元素個數固定使用陣列,元素個數不確定或需要增刪改查使用集合
集合類繼承體系
Collection
-
List 當中可以有重複元素,List 當中 add 方法永遠返回 true
-
Set 當中不能有重複元素,add 重複元素返回 false
-
add()
-
addAll(),新增另一個集合所有元素
-
remove()
-
removeAll(),刪除兩個集合的交集
-
contains()
-
containsAll(),是否包含傳入集合
-
retainAll(),取交集,原集合改變返回 true
-
clear()
-
isEmpty()
-
size()
-
遍歷
-
先把集合轉成陣列 toArray(),返回 Object 陣列
-
foreach 遍歷
-
迭代器遍歷,裡面的物件會自動提升到 Object 型別。Iterator 是一個介面,每一個實現類都重寫了裡面的方法
Iterator it = lsit.iterator(); while (it.hasNext()){ System.out.println(it.next()); }
-
迭代器遍歷時刪除,只能使用迭代器刪除,否則會報併發修改異常
-
迭代器遍歷時新增,使用迭代器新增,List 中特有
-
List
有序,可重複
- 可根據腳標新增元素,list.add(i,e)
- 可獲取指定指令碼元素,list.get(i)
- List 中特有的迭代器,有前一個後一個
ArrayList
陣列實現,存放資料有序、可重複。把原有的資料複製出來,再建立一個新陣列,容量增加 50%,把複製的陣列放到新陣列當中,原有的陣列丟棄。
- 有腳標
- 新增,依次往後移動
- 刪除,依次往前移動
- 查改較快,增刪較慢
LinkedList
雙向連結串列實現。
-
往第一個位置新增(移除)元素,list.addFirst()
-
往最後一個位置新增(移除)元素,list.addLast()
-
也能通過腳標獲取元素,但內部實現複雜,效率較慢
-
增刪較快,查改較慢
Vector
陣列實現。Java 1.2 後改進為可實現 List 介面,使用很少。有一些特有的方法,並且內部加鎖,執行緒安全,效率稍低。
- add()
- addElement()
- elements()
陣列與集合的轉換
Arrays.asList();
list.toArray();
- 轉過之後,不能新增刪除,其餘面向物件的方法可用
- 開發當中不會把基本資料型別陣列轉集合,它會把整個陣列當成一個物件
Set
-
無序,不可重複
-
自定義物件相等判斷:不只是覆蓋 equals,還要覆蓋 hashCode
-
hashCode:與記憶體地址對應的一個編號,每一個物件都有唯一的 hashCode
HashSet
雜湊演算法實現。唯一的,無序的。
LinkedHashSet
HashSet 的子類,底層用連結串列實現。Set 集合中唯一保證元素怎麼存怎麼取。
TreeSet
二叉樹演算法實現。用來對元素進行排序。
- 按數字大小排序
- 按字母順序排序
- 按 unicode 碼排序
- 必須存放統一型別資料,否則無法排序
- 自定義物件不能直接新增到 TreeSet 中,需實現 Comparable 介面,並覆蓋當中 compareTo 方法
- compareTo:返回零不新增,返回正數新增到右子樹,返回負數新增到左子樹
- 比較器:定義一個類實現 Comparator 介面,並覆蓋當中 compare 方法
- compare:返回零不新增,返回正數新增到右子樹,返回負數新增到左子樹
Map
- 是個介面,也叫對映關係,元素無序,維護兩個集合
- A 集合中的每一個元素,都能在 B 集合中找到與之對應的元素
- A 集合元素不能重複,稱為 key
- B 集合元素可以重複,稱為 value
- 新增 put(key,value):key 第一次新增,返回 null,key 不是第一次新增,替換 value,返回原 value
- 清空 clear()
- 刪除 remove(key):刪除 key-value entry
- 長度,size(),返回 int
- 獲取一個元素,get(key),返回 value
- 獲取所有元素
- 取出所有 key
- 遍歷 key 取出 value
- 獲取所有元素,entrySet()
- 自定義 key 型別,覆蓋 hashCode 和 equals 方法
HashMap
典型 Map,鍵值對。
HashMap 和 HashTable 的區別:
- 底層都是使用雜湊演算法
- 都是雙列集合
- HashMap 是執行緒不安全的,效率比較高
- HashTable 是執行緒安全的,效率比較低
- HashMap 可以存 null 值(鍵值都可以),HashTable 不能存 null 值
- HashTable 在 Java 1.4 中被重寫,實現了 Map 介面,是個過時的類
LinkedHashMap
元素有序。
TreeMap
元素按 key 排序,排序方式參照 TreeSet。
泛型
廣泛通用的型別,程式碼模板中型別不確定,誰呼叫這段程式碼,誰就可以指明這個型別。
- 類的後面加上
- 在變數前面加上 T
- 建立時指明型別
- 集合中可使用泛型,更安全
- 泛型前後型別必須保持一致
- Java 1.7 開始後面可以省略,菱形語法
- 泛型沒有繼承
- 泛型其實是個語法糖,本質還是 Object 型別,內部還是要進行強制轉換
泛型類
在類上定義了泛型,建立物件時指定
泛型方法
在方法上定義了泛型,只能用在普通方法上,不能用在靜態方法上
自定義泛型
單獨在方法上定義泛型,有引數才有意義,引數確定型別
也可在靜態方法中定義
萬用字元
不知道使用什麼型別接收時,可以用 ? 表示未知。一般只用於接收。
- 泛型的上限,必須是指定型別或子類,? extends Type
- 泛型的下限,必須是指定型別或父類,? super Type
泛型擦除
把一個有泛型的內容賦值給沒有泛型的內容。
異常
Java 程式在執行過程中出現的錯誤。
-
編譯時異常:必須顯式處理,否則無法通過編譯
-
執行時異常:RuntimeException 類及其子類,編譯時不會報錯,執行時終止程式,開發時遇到的主要異常
JVM 是怎麼處理異常的
-
main 方法收到一個異常,可以自己處理,然後繼續執行
-
也可以交由 JVM 處理,控制檯輸出異常資訊,同時終止程式
try...catch...finally
- catch 按順序執行
- Java 1.7 後 catch 可以使用 | 連線捕獲多個異常
- 只要執行了 try,finally 一定執行,除非程式終止,return 都不能阻止(先 return,再 finally)
- finally 一般用於釋放資源,IO 操作中常見
獲取異常資訊
- e.getMessage() //資訊,引數
- e.toString() //類名,資訊
- e.printStackTrace //類名,資訊,位置,從下往上看
throw 丟擲異常
- 丟擲編譯時異常,必須要處理,或繼續往上拋直到有人(最後是 JVM)處理
- 丟擲執行時異常,不需要處理
- throw:定義在方法內,跟的是異常物件,只能丟擲一個異常
- throws:定義在方法聲明後,跟的是異常類,可以丟擲多個異常
自定義異常
- 自定義編譯時異常
- 定義一個類繼承 Exception
- 丟擲自己定義的異常類名
- 要麼處理,要麼向上拋
- 自定義執行時異常
- 定義一個類繼承 RuntimeException
- 丟擲自己定義的異常類名
- 自定義帶引數異常
- 在類當中提供一個有引數的構造方法
- 把引數傳給父類構造方法