1. 基礎(chǔ)語(yǔ)法
2. 面向?qū)ο?/h5>
3. 常用API、常用類(lèi)型
4. 集合
5. 多線(xiàn)程(線(xiàn)程狀態(tài)、線(xiàn)程安全、線(xiàn)程池、線(xiàn)程間通信)
6. IO
7. 其它(Swing開(kāi)發(fā)、異常正則表達(dá)式、TCP、Socket、HTTP、爬蟲(chóng))
一、基礎(chǔ)語(yǔ)法
- 數(shù)據(jù)類(lèi)型
1. 基本類(lèi)型(8種:byte-8bit整數(shù)、short-16bit整數(shù)、int-32bit整數(shù)、long-64bit整數(shù)、float-32bit浮點(diǎn)、double-64bit浮點(diǎn)、boolean、char-16bit字符)
2. 引用類(lèi)型(存儲(chǔ)對(duì)象的地址值、也就是我們常說(shuō)的指針。Java中string是引用類(lèi)型)
提問(wèn):string str1= ""; string str2= null;區(qū)別就是str1指向的對(duì)象內(nèi)容為空,str2就是沒(méi)有指向任何對(duì)象。
- 變量的初始化
- 任何變量在使用之前都必須先初始化(賦值)
- 局部變量:需要程序員手動(dòng)初始化
- 非局部變量(實(shí)例變量也就是實(shí)例變量、類(lèi)變量也就是static):編譯器會(huì)自動(dòng)給未初始化的變量設(shè)置一個(gè)初始值
-
運(yùn)算符
-
>> 與 >>>
截屏2021-01-27 下午3.44.36.png
- boolean 在判斷語(yǔ)句中,必須是boolean類(lèi)型才行。Java中(
&& ||)的bool判斷具有短路功能,Java中(& |)的bool沒(méi)有短路功能。
-
類(lèi)型轉(zhuǎn)換
- 小轉(zhuǎn)大,自動(dòng)轉(zhuǎn)(隱式轉(zhuǎn)換); 大轉(zhuǎn)小,必須強(qiáng)轉(zhuǎn)(也就是必須添加強(qiáng)轉(zhuǎn)的類(lèi)型)。
- 數(shù)組創(chuàng)建
- int [] arr1; int【】 arr2 = {}; int arr3[ ] = {};
- Java中 字符串?dāng)?shù)組不等于字符串 。
-
數(shù)組索引如何實(shí)現(xiàn)。比如int aray[n] 如何快速查找到。(隨機(jī)訪(fǎng)問(wèn)、速度快、O(1))
array的地址0x1110,那么array[n] = 0x1110 + n*4 即可找到目前對(duì)象地址。4是取決于什么元素,int是4字節(jié),long是8字節(jié)。
截屏2021-01-27 下午5.45.56.png
方法
可變參數(shù) 注意用 (int... numbers)
public static void main(String[] args) {
System.out.println(sum());
System.out.println(sumTest(new int[] {10,20,30}));
}
// 可變就是隨便你定,外部參數(shù)為null也是可以的。允許外界直接傳整數(shù),然后numbers可以將整數(shù)初始化數(shù)組,什么都不傳numbers的長(zhǎng)度為0
// 也就是numbers會(huì)把外面?zhèn)魅氲膎ull轉(zhuǎn)換為一個(gè)空數(shù)組,所以可以放心使用numbers
public static int sum(int... numbers) {
System.out.println(numbers.length);
return 2;
}
// 如果參數(shù)這么寫(xiě),要求外界引用時(shí)候必須傳數(shù)組,如果外面?zhèn)魅霐?shù)組為null那么方法內(nèi)部使用numbers就會(huì)報(bào)錯(cuò)。
public static int sumTest(int[] numbers) {
System.out.println(numbers.length);
return 2;
}
-
參數(shù)傳遞
- 基本類(lèi)型作為參數(shù)是值傳遞,返回值返回的也是值。
- 引用類(lèi)型作為參數(shù)是引用傳遞(地址傳遞),其返回也是地址傳遞。
方法簽名(Method、Signature)
由兩部分組成:方法名、參數(shù)類(lèi)型。
方法重載(OverLoad)
Java的方法支持重載:方法名相同,方法簽名不同。
也就是方法名相同,參數(shù)個(gè)數(shù)不同,參數(shù)類(lèi)型不同
棧幀(stack frame)
棧幀隨著方法的調(diào)用而創(chuàng)建,隨著方法結(jié)束而銷(xiāo)毀,存儲(chǔ)了方法的局部變量信息。
-
遞歸調(diào)用
如果遞歸調(diào)用沒(méi)有終止,將會(huì)一直消耗??臻g
最終導(dǎo)致棧內(nèi)存溢出(Stack Overflow)
所以必須要有一個(gè)明確的結(jié)束遞歸的條件
也叫做邊界條件、遞歸基。
截屏2021-01-27 下午7.59.21.png
-
Java一些特性
- Java一個(gè)類(lèi)只有一個(gè)main,多個(gè)類(lèi)可以有多個(gè)main,編譯執(zhí)行時(shí)候編譯的哪個(gè)類(lèi)則執(zhí)行哪個(gè)類(lèi)的main方法。
- 注釋。單行、多行、文檔注釋?zhuān)?**+enter)
- IDEA中如何關(guān)聯(lián) JDK源碼。
1. 基本類(lèi)型(8種:byte-8bit整數(shù)、short-16bit整數(shù)、int-32bit整數(shù)、long-64bit整數(shù)、float-32bit浮點(diǎn)、double-64bit浮點(diǎn)、boolean、char-16bit字符)
2. 引用類(lèi)型(存儲(chǔ)對(duì)象的地址值、也就是我們常說(shuō)的指針。Java中string是引用類(lèi)型)
提問(wèn):string str1= ""; string str2= null;區(qū)別就是str1指向的對(duì)象內(nèi)容為空,str2就是沒(méi)有指向任何對(duì)象。
- 任何變量在使用之前都必須先初始化(賦值)
- 局部變量:需要程序員手動(dòng)初始化
- 非局部變量(實(shí)例變量也就是實(shí)例變量、類(lèi)變量也就是static):編譯器會(huì)自動(dòng)給未初始化的變量設(shè)置一個(gè)初始值
運(yùn)算符
-
>>與>>>
截屏2021-01-27 下午3.44.36.png - boolean 在判斷語(yǔ)句中,必須是boolean類(lèi)型才行。Java中(
&&||)的bool判斷具有短路功能,Java中(&|)的bool沒(méi)有短路功能。
類(lèi)型轉(zhuǎn)換
- 小轉(zhuǎn)大,自動(dòng)轉(zhuǎn)(隱式轉(zhuǎn)換); 大轉(zhuǎn)小,必須強(qiáng)轉(zhuǎn)(也就是必須添加強(qiáng)轉(zhuǎn)的類(lèi)型)。
- int [] arr1; int【】 arr2 = {}; int arr3[ ] = {};
- Java中 字符串?dāng)?shù)組不等于字符串 。
-
數(shù)組索引如何實(shí)現(xiàn)。比如int aray[n] 如何快速查找到。(隨機(jī)訪(fǎng)問(wèn)、速度快、O(1))
array的地址0x1110,那么array[n] = 0x1110 + n*4 即可找到目前對(duì)象地址。4是取決于什么元素,int是4字節(jié),long是8字節(jié)。
截屏2021-01-27 下午5.45.56.png
方法
可變參數(shù) 注意用 (int... numbers)
public static void main(String[] args) {
System.out.println(sum());
System.out.println(sumTest(new int[] {10,20,30}));
}
// 可變就是隨便你定,外部參數(shù)為null也是可以的。允許外界直接傳整數(shù),然后numbers可以將整數(shù)初始化數(shù)組,什么都不傳numbers的長(zhǎng)度為0
// 也就是numbers會(huì)把外面?zhèn)魅氲膎ull轉(zhuǎn)換為一個(gè)空數(shù)組,所以可以放心使用numbers
public static int sum(int... numbers) {
System.out.println(numbers.length);
return 2;
}
// 如果參數(shù)這么寫(xiě),要求外界引用時(shí)候必須傳數(shù)組,如果外面?zhèn)魅霐?shù)組為null那么方法內(nèi)部使用numbers就會(huì)報(bào)錯(cuò)。
public static int sumTest(int[] numbers) {
System.out.println(numbers.length);
return 2;
}
參數(shù)傳遞
- 基本類(lèi)型作為參數(shù)是值傳遞,返回值返回的也是值。
- 引用類(lèi)型作為參數(shù)是引用傳遞(地址傳遞),其返回也是地址傳遞。
方法簽名(Method、Signature)
由兩部分組成:方法名、參數(shù)類(lèi)型。
方法重載(OverLoad)
Java的方法支持重載:方法名相同,方法簽名不同。
也就是方法名相同,參數(shù)個(gè)數(shù)不同,參數(shù)類(lèi)型不同
棧幀(stack frame)
棧幀隨著方法的調(diào)用而創(chuàng)建,隨著方法結(jié)束而銷(xiāo)毀,存儲(chǔ)了方法的局部變量信息。
遞歸調(diào)用
如果遞歸調(diào)用沒(méi)有終止,將會(huì)一直消耗??臻g
最終導(dǎo)致棧內(nèi)存溢出(Stack Overflow)
所以必須要有一個(gè)明確的結(jié)束遞歸的條件
也叫做邊界條件、遞歸基。

Java一些特性
- Java一個(gè)類(lèi)只有一個(gè)main,多個(gè)類(lèi)可以有多個(gè)main,編譯執(zhí)行時(shí)候編譯的哪個(gè)類(lèi)則執(zhí)行哪個(gè)類(lèi)的main方法。
- 注釋。單行、多行、文檔注釋?zhuān)?**+enter)
- IDEA中如何關(guān)聯(lián) JDK源碼。
Java SE 就是Java語(yǔ)言基礎(chǔ)
二、面向?qū)ο?/h3>
- 對(duì)象與數(shù)組的內(nèi)存分析
- 內(nèi)存區(qū)域劃分
- 構(gòu)造方法
- 包
- 繼承
- 重寫(xiě)_super
- 構(gòu)造方法細(xì)節(jié)
- Annotation
- 訪(fǎng)問(wèn)控制
- 封裝_toString
- static
- 靜態(tài)導(dǎo)入
- 初始化
- 單例模式
- final_常量
- 內(nèi)部類(lèi)
- 靜態(tài)嵌套類(lèi)
- 局部類(lèi)
- 抽象類(lèi)
- 接口01_基本使用
- 接口02_細(xì)節(jié)
- 接口03_對(duì)比抽象類(lèi)
- 接口04_默認(rèn)方法
- 接口05_靜態(tài)方法
- 多態(tài)
- 使用接口的好處
- 匿名類(lèi)01_基本使用
- 匿名類(lèi)02_用途
- 匿名類(lèi)03_排序
- Lambda01_基本使用
- Lambda02_使用注意
- 方法引用
1. 對(duì)象與數(shù)組的內(nèi)存分析
- 對(duì)象內(nèi)存new 出來(lái)的對(duì)象是在堆空間,方法內(nèi)部的變量dog、person這個(gè)在棧的方法里。

-
數(shù)組內(nèi)存:
如下圖,dogs指向Dog[7]的首地址,Dog[7]中存放的是7個(gè)地址,然后每個(gè)地址再指向一個(gè)實(shí)例dog對(duì)象。
截屏2021-01-28 下午5.00.38.png
2. Java程序的內(nèi)存劃分
Java虛擬機(jī)在執(zhí)行Java程序時(shí)會(huì)將內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。
PC寄存器:存儲(chǔ)Java虛擬機(jī)正在執(zhí)行的字節(jié)碼指令的地址。
Java 虛擬機(jī)棧: 存儲(chǔ)棧幀。
堆:存儲(chǔ)GC(垃圾回收)所管理的各種對(duì)象。也就是平時(shí)new出來(lái)的對(duì)象。
方法區(qū):存儲(chǔ)每一個(gè)類(lèi)的結(jié)構(gòu)信息.(結(jié)構(gòu)信息:字段和方法信息、構(gòu)造方法和普通方法的字節(jié)碼等)
本地方法棧:支持native方法的調(diào)用。(比如用C語(yǔ)言編寫(xiě)的)
3. 構(gòu)造方法 Constructor
只有在構(gòu)造方法里,才可以使用this\super調(diào)用別的構(gòu)造方法

this
this 本質(zhì)是一個(gè)隱藏的、位置最靠前的方法參數(shù)。
只要面向?qū)ο蟮木幊陶Z(yǔ)言,其實(shí)this、self的本質(zhì)都是一樣的。

4. 包(package)
Java中包就是其他編程語(yǔ)言中的命名空間,包的本質(zhì)是文件夾。
將不同的類(lèi)進(jìn)行組織管理、訪(fǎng)問(wèn)控制
解決命名沖突
為解決包名的唯一性,一般包名都是以公司域名的倒寫(xiě)開(kāi)頭,比如com.baidu.
全小寫(xiě)
類(lèi)的第一句代碼必須使用package聲明自己屬于哪個(gè)包。如:package com.baidu.model;
導(dǎo)入包 import xxx
5. 繼承(Inheritance)
Java中對(duì)象都是繼承自基類(lèi)Object。
Student 繼承自 Person ,那么Person中存在的成員變量被Student繼承。person、student對(duì)象分別在堆中開(kāi)辟內(nèi)存,每個(gè)對(duì)象中都存在基類(lèi)person的age,同時(shí)student也會(huì)存在自己成員變量age。
總結(jié)一下:子類(lèi)對(duì)象包含父類(lèi)所有成員屬性,父類(lèi)私有變量也是存在,只是編譯時(shí)候?qū)υL(fǎng)問(wèn)權(quán)限進(jìn)行的控制,但是不影響在子類(lèi)對(duì)象內(nèi)存在(可以通過(guò)set 、get進(jìn)行設(shè)置、讀?。?/p>

6. 方法的重寫(xiě)(Override)
重點(diǎn): 子類(lèi)的方法簽名與父類(lèi)一樣。
子類(lèi)重寫(xiě)的方法權(quán)限必須 大于 父類(lèi)的方法權(quán)限
子類(lèi)重寫(xiě)的方法返回值類(lèi)型必須 小于 父類(lèi)的方法返回值類(lèi)型
子類(lèi) <= 父類(lèi)
7.構(gòu)造方法細(xì)節(jié)
super
訪(fǎng)問(wèn)父類(lèi)中定義的成員變量
訪(fǎng)問(wèn)父類(lèi)匯總定義的方法(包括構(gòu)造方法)
子類(lèi)的構(gòu)造方法必須先調(diào)用父類(lèi)的構(gòu)造方法,再執(zhí)行后面的代碼。(不同語(yǔ)言有不同語(yǔ)言的特性,Java語(yǔ)言中子類(lèi)的構(gòu)造是先默認(rèn)調(diào)用了父類(lèi)的構(gòu)造)
編譯器會(huì)自動(dòng)調(diào)用父類(lèi)無(wú)參的構(gòu)造方法(若此時(shí)父類(lèi)沒(méi)有無(wú)參的構(gòu)造方法,編譯器將報(bào)錯(cuò))
8. 注解(Annotation)
@Override :告訴編譯器這是一個(gè)重寫(xiě)后的方法 。方法簽名要一致才行。
@SuppressWarnings(”警告類(lèi)別“):讓編譯器不生成警告信息
9. 訪(fǎng)問(wèn)控制(Access Control)
Java中存在4個(gè)基本訪(fǎng)問(wèn)權(quán)限,從高到低如下所示
1. public:在任何地方都是可見(jiàn)的
2. protected:盡在自己的包中,自己的子類(lèi)中可見(jiàn)
3. 無(wú)修飾符(什么都不寫(xiě)):僅在自己的包中可見(jiàn)。
4. private:僅在自己的類(lèi)中可見(jiàn)
上述4中訪(fǎng)問(wèn)權(quán)限都可以修飾類(lèi)的成員(成員變量、方法、嵌套類(lèi)等)
只有public 、無(wú)修飾符可以修飾頂級(jí)類(lèi)(Top-level Class)
上述4個(gè)訪(fǎng)問(wèn)權(quán)限不可以修飾局部類(lèi)(Local Class)、局部變量
一個(gè)Java源文件中可以定義多個(gè)頂級(jí)類(lèi),public頂級(jí)類(lèi)的名字必須和文件名一樣
10. 封裝_toString
成員變量 private化,提供public的getter、setter。
建議提供一個(gè)無(wú)參的構(gòu)造函數(shù)。
我們可以重寫(xiě)對(duì)象的toString方法
public class Person {
private int age;
private String name;
public init getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
封裝、繼承、多態(tài)。三大特性。。。
11. static_final
static 常用來(lái)修飾類(lèi)的成員:成員變量、方法、嵌套類(lèi)。
我們需要知道創(chuàng)建多少個(gè)對(duì)象時(shí)候,構(gòu)造函數(shù)統(tǒng)計(jì)static數(shù)據(jù)++就行。
static修飾成員變量:
程序運(yùn)行過(guò)程中只占用一份固定的內(nèi)存(存儲(chǔ)在方法區(qū)、全世界只有一份內(nèi)存)
可以通過(guò)實(shí)例、類(lèi)訪(fǎng)問(wèn)
沒(méi)有static修飾成員變量:
在每個(gè)實(shí)例內(nèi)部都有一份內(nèi)存
只能通過(guò)實(shí)例訪(fǎng)問(wèn),不可以通過(guò)類(lèi)訪(fǎng)問(wèn)。
static修飾方法:
1. 被static修飾的方法叫做:類(lèi)方法、靜態(tài)方法。
2. 內(nèi)部不允許使用this。(this本質(zhì)是實(shí)例對(duì)象在用方法時(shí)候把自身對(duì)象傳入方法內(nèi)部,所以static修飾的方法不能用this)
3. 可以直接訪(fǎng)問(wèn)類(lèi)變量、類(lèi)方法
4. 不可以直接訪(fǎng)問(wèn)實(shí)例變量、實(shí)例方法(由于類(lèi)方法中沒(méi)有this,所以不可以調(diào)用實(shí)例變量,實(shí)例方法)
沒(méi)用static修飾方法稱(chēng)之為實(shí)例方法:
1. 實(shí)例方法只能通過(guò)實(shí)例訪(fǎng)問(wèn),不可以通過(guò)類(lèi)訪(fǎng)問(wèn)
2. 內(nèi)部可以使用this
3. 可以直接訪(fǎng)問(wèn)實(shí)例變量、實(shí)例方法
4. 可以直接訪(fǎng)問(wèn)類(lèi)變量、類(lèi)方法
不能有同名的實(shí)例變量和類(lèi)變量。不能有相同簽名的實(shí)例方法和類(lèi)方法
12. 靜態(tài)導(dǎo)入
靜態(tài)導(dǎo)入后,可以省略類(lèi)名來(lái)訪(fǎng)問(wèn)靜態(tài)成員(成員變量、方法、嵌套類(lèi))

13. 初始化

14. 單例模式(Singleton Pattern)
1. 構(gòu)造方法私有化。(禁止外面調(diào)用構(gòu)造方法)
2. 公告的靜態(tài)的方法,返回唯一的那個(gè)實(shí)例
3. 私有的靜態(tài)的實(shí)例變量
/***
* 餓漢式單例模式,上來(lái)就先創(chuàng)建一個(gè)單例對(duì)象
*/
public class Person {
// 私有的靜態(tài)的實(shí)例變量
private static Person instance = new Person();
// 構(gòu)造方法私有化
private Person() {
}
// 公共的靜態(tài)的方法,返回唯一的那個(gè)實(shí)例
public static Person getInstance() {
return instance;
}
}
/***
* 懶漢式單利模式,需要的時(shí)候調(diào)用生成
*/
public class Person {
// 私有的靜態(tài)的實(shí)例變量
private static Person instance = null;
// 構(gòu)造方法私有化
private Person() {
}
// 存在線(xiàn)程不安全的問(wèn)題。多個(gè)線(xiàn)程同時(shí)調(diào)用的時(shí)候,多條線(xiàn)程同時(shí)創(chuàng)建多個(gè)instance,但是后期是唯一的,但仍然在開(kāi)始創(chuàng)建時(shí)不安全。
public static Person getInstance() {
if (instance == null) {
instance = new Person();
}
return instance;
}
}
餓漢式單例沒(méi)有線(xiàn)程安全問(wèn)題,懶漢式單例存在線(xiàn)程安全問(wèn)題。線(xiàn)程安全問(wèn)題,一旦加了鎖,效率都會(huì)降低。所以我們可以直接用餓漢式單例。
15. final_常量
1. 被final修飾的類(lèi):`不能被繼承`
2. 被final修飾的方法:不能被重寫(xiě)
3. 被final修飾的變量:只能進(jìn)行1次賦值
Java 中說(shuō)的常量。命名規(guī)范常量全是大寫(xiě)字母
public static final double PI = 3.141592653;
通過(guò)指的 static final這種修飾的
如果將基本類(lèi)型或字符串定義為常量,并且在編譯時(shí)就能確定值
編譯器會(huì)使用常量值替代各處的常量名(類(lèi)似于C預(yù)言的宏替換)
成為編譯時(shí)常量
16. 嵌套類(lèi)(Nested Class)
嵌套類(lèi):定義在另一個(gè)類(lèi)中的類(lèi)。
靜態(tài)嵌套類(lèi)(static修飾的)
非靜態(tài)嵌套類(lèi)(內(nèi)部類(lèi))
內(nèi)部類(lèi):是先創(chuàng)建外層的對(duì)象,然后再創(chuàng)建內(nèi)部類(lèi)對(duì)象person.new。內(nèi)存表示如下如:

內(nèi)部類(lèi):沒(méi)有被`static`修飾的嵌套類(lèi),非靜態(tài)嵌套類(lèi)。
跟實(shí)例變量、實(shí)例方法一樣,內(nèi)部類(lèi)與外部類(lèi)的實(shí)例相關(guān)聯(lián)。
必須先創(chuàng)建外部類(lèi)實(shí)例,然后再用外部類(lèi)實(shí)例創(chuàng)建內(nèi)部類(lèi)實(shí)例
內(nèi)部類(lèi)不能定義除編譯時(shí)常量意外的任何`static`成員
內(nèi)部類(lèi)可以直接訪(fǎng)問(wèn)外部類(lèi)中的所有成員(即使被聲明為`private`)
外部類(lèi)可以直接訪(fǎng)問(wèn)內(nèi)部類(lèi)實(shí)例的成員變量、方法(即使被聲明為`private`)
17. 靜態(tài)嵌套類(lèi)(Nested Class)
- 靜態(tài)嵌套類(lèi):被
static修飾的嵌套類(lèi)
2.靜態(tài)嵌套類(lèi)在行為上就是一個(gè)頂級(jí)類(lèi),只是定義的代碼寫(xiě)在了另一個(gè)類(lèi)中。 - 對(duì)比一般的頂級(jí)類(lèi),靜態(tài)嵌套類(lèi)多了一些特殊權(quán)限
- 可以直接訪(fǎng)問(wèn)外部類(lèi)中的成員(即使被聲明為
private)
什么情況使用嵌套類(lèi)?
如果類(lèi)A只用在類(lèi)C內(nèi)部,可以考慮將類(lèi)A嵌套到類(lèi)C中
封裝性更好
程序包更加簡(jiǎn)化
增強(qiáng)可讀性、維護(hù)性
如果類(lèi)A需要經(jīng)常訪(fǎng)問(wèn)類(lèi)C的非公共成員,可以考慮將類(lèi)A嵌套到類(lèi)C中
另外也可以根據(jù)需要將類(lèi)A隱藏起來(lái),不對(duì)外暴露
如果需要經(jīng)常訪(fǎng)問(wèn)非公共的實(shí)例成員,設(shè)計(jì)成內(nèi)部類(lèi)(非靜態(tài)嵌套類(lèi)),否則設(shè)計(jì)及成靜態(tài)嵌套類(lèi)
如果必須先有C實(shí)例,才能創(chuàng)建A實(shí)例,那么可以將A涉及為C的內(nèi)部類(lèi)。
18.局部類(lèi)(Local Class)
局部類(lèi):定義在代碼塊中的類(lèi)(可以定義在方法中、for循環(huán)中、if語(yǔ)句中等)
局部類(lèi)不能定義除編譯時(shí)常量以外的任何static成員
局部類(lèi)只能訪(fǎng)問(wèn) final 或者 有效 final 的局部變量
局部類(lèi)可以直接訪(fǎng)問(wèn)外部類(lèi)中的所有成員。(即使被聲明為private)
局部類(lèi)只有定義在實(shí)例先關(guān)的代碼塊中,才能直接訪(fǎng)問(wèn)外部類(lèi)中的實(shí)例成員(實(shí)例變量、實(shí)例方法)
19.抽象類(lèi)(Local Class)
抽象方法(Abstract Method)
抽象方法:被 `abstract`修飾的方法
只有方法聲明,沒(méi)有方法實(shí)現(xiàn)(參數(shù)列表后面沒(méi)有大括號(hào),而是分號(hào))
不能是 `private`權(quán)限(因?yàn)槎x抽象方法的目的讓子類(lèi)去實(shí)現(xiàn))
只能是實(shí)例方法,不能是類(lèi)方法。
只能定義在抽象類(lèi)、接口中
抽象類(lèi)
抽象類(lèi):被 `abstract`修飾的類(lèi)(此類(lèi)就是作為父類(lèi)被繼承用的)
可以定義抽象方法
不能實(shí)例化,但可以自定義構(gòu)造方法(等著被子類(lèi)去調(diào)用??)
子類(lèi)必須實(shí)現(xiàn)抽象父類(lèi)中的所有抽象方法(除非子類(lèi)也是一個(gè)抽象類(lèi))
可以像非抽象類(lèi)一樣定義成員變量、常量、嵌套類(lèi)型、初始化塊、非抽象方法等
為什么使用抽象類(lèi)
抽取子類(lèi)的公共實(shí)現(xiàn)到抽象父類(lèi)中,要求子類(lèi)必須要單獨(dú)實(shí)現(xiàn)的定義成抽象方法。
抽象方法是要求子類(lèi)強(qiáng)制實(shí)現(xiàn)的方法。只是堆積抽象公共方法
20.接口01_基本使用
Java中的接口:
一系列方法聲明的集合
用例定義規(guī)范、標(biāo)準(zhǔn)
接口定義:抽象方法、常量、嵌套類(lèi)型。
這個(gè)接口就是規(guī)定 方法(規(guī)范),其它依賴(lài)這個(gè)接口的類(lèi)實(shí)現(xiàn)里面的方法即可。
接口就是:有做哪些能力
21.接口02_細(xì)節(jié)
接口、抽象類(lèi)都不能實(shí)例化。
接口可以在任何使用類(lèi)型的地方使用。
一個(gè)類(lèi)可以通過(guò)`implements`關(guān)鍵字實(shí)現(xiàn)一個(gè)或多個(gè)接口
實(shí)現(xiàn)接口的類(lèi)必須實(shí)現(xiàn)接口中定義的所有抽象方法,除非它是個(gè)抽象類(lèi)
如果一個(gè)類(lèi)實(shí)現(xiàn)的多個(gè)接口中有相同的抽象方法,只需要實(shí)現(xiàn)此方法一次。
`extends`和`implements`可以一起使用,`implements`必須寫(xiě)在`extends`的后面
當(dāng)父類(lèi)、接口中的方法簽名一樣時(shí),那么返回值類(lèi)型也必須一樣
一個(gè)接口可以通過(guò)`extends`關(guān)鍵字繼承一個(gè)或者多個(gè)接口
22.接口03_對(duì)比抽象類(lèi)
抽象類(lèi):
1.繼承 A extends B , A 擁有B 的方法。
接口:
實(shí)現(xiàn):A implements B , A會(huì)B中的行為。
何時(shí)選擇抽象類(lèi)?
- 在緊密先關(guān)的類(lèi)之間共享代碼
- 在要除
public之外的訪(fǎng)問(wèn)權(quán)限 - 需要定義實(shí)例變量、非
final的靜態(tài)變量
何時(shí)選擇接口?
- 不相關(guān)的類(lèi)實(shí)現(xiàn)相同的方法。
- 只是定義行為,不關(guān)心具體是誰(shuí)實(shí)現(xiàn)的行為
- 想實(shí)現(xiàn)類(lèi)型的多重繼承
23.接口04_默認(rèn)方法
接口升級(jí)問(wèn)題:
如果接口需要升級(jí),比如增加新的抽象方法。
會(huì)導(dǎo)致大幅的代碼改動(dòng),以前實(shí)現(xiàn)接口的類(lèi)都需要改動(dòng)。
若想在不改動(dòng)以前實(shí)現(xiàn)類(lèi)的前提下進(jìn)行接口升級(jí)。從Java8開(kāi)始,有2種方法
- 默認(rèn)方法
- 靜態(tài)方法
1. 默認(rèn)方法的使用
當(dāng)一個(gè)類(lèi)實(shí)現(xiàn)的接口中有默認(rèn)方法是,這個(gè)類(lèi)可以
啥也不干,沿用接口的默認(rèn)實(shí)現(xiàn)
重新定義默認(rèn)方法,覆蓋默認(rèn)方法的實(shí)現(xiàn)
重新聲明默認(rèn)方法,將默認(rèn)方法聲明為抽象方法(此類(lèi)必須是抽象類(lèi))
當(dāng)一個(gè)接口繼承的父接口中有默認(rèn)方法時(shí),這個(gè)接口可以
啥也不干,沿用接口的默認(rèn)實(shí)現(xiàn)
重新定義默認(rèn)方法,覆蓋默認(rèn)方法的實(shí)現(xiàn)
重新聲明默認(rèn)方法,將默認(rèn)方法聲明為抽象方法
如果父類(lèi)定義的抽象方法與接口的默認(rèn)方法相同時(shí),要求子類(lèi)實(shí)現(xiàn)此抽象方法
可以通過(guò)super關(guān)鍵字調(diào)用接口的默認(rèn)方法。調(diào)用代碼接口名.super.方法
24.接口05_靜態(tài)方法
定義:
接口中定義的靜態(tài)方法只能通過(guò)接口名調(diào)用,不能被繼承。
類(lèi)是單繼承,接口是多繼承所以靜態(tài)方法不能被繼承下去。
25.多態(tài)(Polymorphism)
什么是多態(tài)?
具有多種形態(tài)
統(tǒng)一操作作用于不同的對(duì)象,產(chǎn)生不同的執(zhí)行結(jié)果
JVM會(huì)根據(jù)引用變量指向的具體對(duì)象來(lái)調(diào)用對(duì)應(yīng)的方法
這個(gè)行為叫做:虛方法調(diào)用
類(lèi)似于C++中的虛函數(shù)調(diào)用
多態(tài)提現(xiàn):
父類(lèi)(接口)類(lèi)型指向子類(lèi)對(duì)象
調(diào)用子類(lèi)重寫(xiě)的方法
靜態(tài)方法中,如果基類(lèi)類(lèi)型那么調(diào)用的時(shí)候還是基類(lèi)的靜態(tài)方法??梢钥匆幌耫og2的方法。

如果沒(méi)有static的則是子類(lèi)方法了
成員變量的訪(fǎng)問(wèn)細(xì)節(jié)

instanceof
可以通過(guò)instanceof判斷某個(gè)類(lèi)型是否屬于某個(gè)類(lèi)型
26.使用接口的好處
面向接口編程
業(yè)務(wù)層==》dao層(數(shù)據(jù)庫(kù))這是最常見(jiàn)的需求
但是我們需要面向接口,也就是 業(yè)務(wù)層是通過(guò)調(diào)用 接口 來(lái)實(shí)現(xiàn)查詢(xún) dao層數(shù)據(jù)??梢宰龅筋?lèi)的解耦。
可以看下面圖:接口是LoginDao,實(shí)現(xiàn)接口LoginDaoH、LoginDaoM的類(lèi),如果需要變更那我們只需要更改這些類(lèi)即可。

27.匿名類(lèi)01_基本使用
匿名類(lèi):當(dāng)接口、抽象類(lèi)的實(shí)現(xiàn)類(lèi),在真?zhèn)€項(xiàng)目中只用過(guò)一次,可以考慮使用匿名類(lèi)。
使用接口,必須要有對(duì)應(yīng)的類(lèi)實(shí)現(xiàn)這個(gè)方法。我們使用這個(gè)類(lèi),就可以把這個(gè)方法實(shí)現(xiàn)。但是假如這個(gè)類(lèi),只使用過(guò)一次,這時(shí)候類(lèi)使用匿名類(lèi)。

28.匿名類(lèi)02_用途
首先演示一下,代碼傳遞。
寫(xiě)一個(gè)工具類(lèi):統(tǒng)計(jì)某一段代碼的執(zhí)行時(shí)間。
工具類(lèi)通常寫(xiě)在一個(gè)包內(nèi)。
package timeTest;
public class Times {
//搞一個(gè)帶接口的 代碼塊
public interface Block {
void execute();
}
//外部傳入代碼塊,傳入的代碼塊中需要實(shí)現(xiàn)接口方法。然后這里測(cè)試執(zhí)行方法實(shí)現(xiàn)需要的時(shí)間
public static void test(Block block) {
long begin = System.currentTimeMillis();
block.execute();
long end = System.currentTimeMillis();
double duration = (end - begin) / 1000;
System.out.println("耗時(shí)" + duration + "s");
}
}
具體使用
import timeTest.Times;
import timeTest.Times.Block;
public class mainTime {
public static void main(String[] args) {
// 匿名類(lèi)執(zhí)行,傳入block塊,實(shí)現(xiàn)block塊里面的接口即可。
Times.test(new Block() {
@Override
public void execute() {
int age = 100000;
String string = "";
for (int i = 0; i < age ; i++) {
string += i;
}
}
});
}
}
當(dāng)然我們可以通過(guò) 類(lèi) 實(shí)現(xiàn)某個(gè)類(lèi)中,某段代碼耗時(shí)問(wèn)題。但是這樣存在的問(wèn)題是不靈活,我們每次都需要寫(xiě)一個(gè)類(lèi)測(cè)試,不如我們直接填入需要測(cè)試的代碼。
回調(diào)
其實(shí)跟代碼傳遞類(lèi)似,只是決定哪個(gè)時(shí)刻調(diào)用哪個(gè)接口方法而已。
過(guò)濾器
1.先把過(guò)濾器內(nèi)部功能實(shí)現(xiàn).內(nèi)部需要實(shí)現(xiàn)傳入的路徑獲取所有文件數(shù)據(jù)。然后對(duì)這些文件數(shù)據(jù)單獨(dú)篩選是否需要返回,再單獨(dú)對(duì)文件進(jìn)行篩選返回的時(shí)候,需要外部對(duì)這個(gè)文件名進(jìn)行選擇確認(rèn),篩選出對(duì)應(yīng)數(shù)據(jù)。
public class Files {
public interface Filter {
boolean accept(String filename);
}
public static String[] getAllFilenames(String dir, Filter filter) {
// 1. 現(xiàn)獲取dir下所有文件名
String[] allFilenames = {};
// 2. 進(jìn)行過(guò)濾
for (String filename: allFilenames) {
if (filter.accept(filename)) {
// 將這個(gè)文件名包裝起來(lái)
}
}
// 3. 返回所有裝起來(lái)的文件名
}
}
- 外部如何調(diào)用,再實(shí)現(xiàn)一下。
import timeTest.Files;
import timeTest.Files.Filter;
public class mainFilter {
public static void main(String[] args) {
Files.getAllFilenames("F",new Filter(){
@Override
public boolean accept(String filename) {
return filename.contains("過(guò)濾內(nèi)容條件");
}
});
}
}
29.匿名類(lèi)03_排序
Array.sort默認(rèn)是升序排列
會(huì)把小的放左邊,大的放右邊。
30.Lambda Expression
函數(shù)式接口:只包含一個(gè)抽象方法的接口。
前面添加@FunctionalInterface表示函數(shù)是接口,規(guī)范。
// 標(biāo)準(zhǔn)形式
(參數(shù)列表) -> {
return xxxxx;
}
//簡(jiǎn)寫(xiě)形式
(參數(shù)A、參數(shù)B) -> xx
31.Lambda 的使用注意
只能訪(fǎng)問(wèn)final或者有效 final的局部變量
沒(méi)用引入新的作用域
32.方法引用
種類(lèi)::方法
對(duì)于lambda的一種簡(jiǎn)化.如果Lambda中的內(nèi)容僅僅是調(diào)用某個(gè)方法,可以使用方法調(diào)用來(lái)簡(jiǎn)化。
引用類(lèi)方法
Testable t1 = (v1, v2) -> Math.max(v1,v2);或者Testable t1 = (v1, v2) -> Math::max;-
引用特定對(duì)象的實(shí)例方法
截屏2021-02-25 上午11.46.46.png 運(yùn)用特定類(lèi)型的任意對(duì)象的實(shí)例方法
引用構(gòu)造方法
引用數(shù)組的構(gòu)造方法
引用當(dāng)前類(lèi)中定義的實(shí)例方法
引用父類(lèi)中定義的實(shí)例方法
三、常用類(lèi)型
- 枚舉
- 包裝類(lèi)01_基本使用
- 包裝類(lèi)02_細(xì)節(jié)
- Math_Random_UUID
- 數(shù)字格式化_BigDecimal
- String01
- String02_intern
- String03_常用方法
- StringBuilder
- Date_Calendar
1.枚舉 ENUM
枚舉目的是保證變量的取值為固定的那幾種。
如果一個(gè)變量的取值只可能是固定的幾個(gè)值,那么可以考慮枚舉類(lèi)型。
枚舉由一組預(yù)定義的常量構(gòu)成
public enum Season {
SPRING, SUMMER, FALL, WINTER
}
Season s = Season.WINTER;
枚舉的本質(zhì)就是類(lèi)
枚舉的構(gòu)造方法權(quán)限必須是無(wú)修飾符 或者 private
Java枚舉會(huì)主動(dòng)調(diào)用構(gòu)造方法初始化每一個(gè)常量,你不能主動(dòng)調(diào)用構(gòu)造方法。初始化常量時(shí)候自己主動(dòng)調(diào)用。
2.包裝類(lèi)01_基本使用
基本類(lèi)型的缺陷
對(duì)比引用類(lèi)型,基本類(lèi)型存在的一些缺陷
- 無(wú)法表示不存在的值(也就是不存在null值)
- 不能利用面向?qū)ο蟮姆绞饺ゲ僮骰绢?lèi)型(比如直接用基本類(lèi)型調(diào)用方法)
- 當(dāng)方法參數(shù)是引用類(lèi)型時(shí),基本類(lèi)型無(wú)法傳遞。
解決辦法,將基本類(lèi)型包裝成引用類(lèi)型
public class IntObject {
public int value;
public IntObject(int value) {
this.value = value;
}
}
包裝類(lèi)(Wrapper Class)
Java中已經(jīng)內(nèi)置了基本類(lèi)型的包裝類(lèi)(都在java.lang包中)

基本類(lèi)型與包裝類(lèi)的關(guān)系,這點(diǎn)要搞明白。
自動(dòng)裝箱:基本類(lèi)型轉(zhuǎn)為引用類(lèi)型。
自動(dòng)拆箱:引用類(lèi)型轉(zhuǎn)為基本類(lèi)型。
轉(zhuǎn)的時(shí)候,注意緩存中數(shù)據(jù)大小[-128, 127]范圍的Integer對(duì)象
包裝類(lèi)的判等 引用類(lèi)型中 == 比較的是內(nèi)存地址。

這個(gè)就是127內(nèi)整數(shù),有緩存是同一個(gè)對(duì)象。new的話(huà)就是新的對(duì)象,所以不是同一對(duì)象。

使用注意
基本數(shù)據(jù)數(shù)組 與 包裝類(lèi)數(shù)組之間不能自動(dòng)裝箱、拆箱的。
需要遍歷,然后加入數(shù)組內(nèi)部。
3.包裝類(lèi)02_細(xì)節(jié)
Math

4. Math_Random_UUID
Random產(chǎn)生隨意數(shù)
UUID
通用唯一標(biāo)識(shí)符
分布式系統(tǒng)上面用的
5. 數(shù)字格式化_BigDecimal


高精度計(jì)算
float、double存儲(chǔ)的小數(shù)只是存的近似值,并非精準(zhǔn)值。因此不適合用來(lái)進(jìn)行高精度計(jì)算
小數(shù)轉(zhuǎn)二進(jìn)制常識(shí)問(wèn)題,乘以2,乘以2這樣進(jìn)行推算出二進(jìn)制數(shù)

使用BitDecimal進(jìn)行高精度計(jì)算,使用字符串進(jìn)行計(jì)算就是準(zhǔn)確的了。
原理:大數(shù)乘法。底層是將字符串單獨(dú)存儲(chǔ),然后按位進(jìn)行乘、加等
6. String01
底層用char[ ] 存儲(chǔ)字符數(shù)據(jù),但是從Java 9 開(kāi)始,底層使用byte[ ] 存儲(chǔ)字符數(shù)據(jù)。
思考一下,為什么之前用 char,后面改為byte。
小小知識(shí)點(diǎn)
Java中,{ }表示的數(shù)組,但是JavaScript中表示的一個(gè)對(duì)象,iOS中表示一個(gè)字典也就是對(duì)象。
Block是什么?
Block是C語(yǔ)言的一個(gè)語(yǔ)法特性,同時(shí)也是C語(yǔ)言的運(yùn)行時(shí)特性,它很像C中的函數(shù)指針,因?yàn)槟憧梢韵袷褂煤瘮?shù)指針一樣的去使用block對(duì)象;它也很像C++中的函數(shù)對(duì)象,因?yàn)槌艘獔?zhí)行的代碼,block還可以攜帶和block綁定的狀態(tài)信息。
因此,block是一個(gè)對(duì)象,這個(gè)對(duì)象里包含了要執(zhí)行的代碼片段以及一些狀態(tài)信息。



