Java 基礎(chǔ)

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ì)象。
  • 變量的初始化
    • 任何變量在使用之前都必須先初始化(賦值)
    1. 局部變量:需要程序員手動(dòng)初始化
    2. 非局部變量(實(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)建
    1. int [] arr1; int【】 arr2 = {}; int arr3[ ] = {};
    2. 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一些特性

    1. Java一個(gè)類(lèi)只有一個(gè)main,多個(gè)類(lèi)可以有多個(gè)main,編譯執(zhí)行時(shí)候編譯的哪個(gè)類(lèi)則執(zhí)行哪個(gè)類(lèi)的main方法。
    2. 注釋。單行、多行、文檔注釋?zhuān)?**+enter)
    3. 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)造方法

截屏2021-01-28 下午6.02.54.png

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

截屏2021-01-28 下午6.26.57.png

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>

截屏2021-01-28 下午7.14.44.png

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))

截屏2021-01-29 下午4.05.09.png

13. 初始化

截屏2021-01-29 下午4.40.54.png

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)存表示如下如:


截屏2021-02-01 下午4.44.14.png
內(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)

  1. 靜態(tài)嵌套類(lèi):被static修飾的嵌套類(lèi)
    2.靜態(tài)嵌套類(lèi)在行為上就是一個(gè)頂級(jí)類(lèi),只是定義的代碼寫(xiě)在了另一個(gè)類(lèi)中。
  2. 對(duì)比一般的頂級(jí)類(lèi),靜態(tài)嵌套類(lèi)多了一些特殊權(quán)限
  3. 可以直接訪(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)?

  1. 在緊密先關(guān)的類(lèi)之間共享代碼
  2. 在要除public之外的訪(fǎng)問(wèn)權(quán)限
  3. 需要定義實(shí)例變量、非final的靜態(tài)變量

何時(shí)選擇接口?

  1. 不相關(guān)的類(lèi)實(shí)現(xiàn)相同的方法。
  2. 只是定義行為,不關(guān)心具體是誰(shuí)實(shí)現(xiàn)的行為
  3. 想實(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種方法

  1. 默認(rèn)方法
  2. 靜態(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的方法。

截屏2021-02-03 下午4.11.16.png

如果沒(méi)有static的則是子類(lèi)方法了

成員變量的訪(fǎng)問(wèn)細(xì)節(jié)

截屏2021-02-03 下午4.32.22.png

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)即可。


截屏2021-02-04 下午6.45.33.png

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)。

截屏2021-02-05 下午2.47.56.png

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)的文件名
    }
}
  1. 外部如何調(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)化。

  1. 引用類(lèi)方法 Testable t1 = (v1, v2) -> Math.max(v1,v2);或者 Testable t1 = (v1, v2) -> Math::max;

  2. 引用特定對(duì)象的實(shí)例方法


    截屏2021-02-25 上午11.46.46.png
  3. 運(yùn)用特定類(lèi)型的任意對(duì)象的實(shí)例方法

  4. 引用構(gòu)造方法

  5. 引用數(shù)組的構(gòu)造方法

  6. 引用當(dāng)前類(lèi)中定義的實(shí)例方法

  7. 引用父類(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包中)

截屏2021-02-25 下午4.46.45.png

基本類(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)存地址。

截屏2021-02-26 上午11.21.29.png

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


截屏2021-02-26 上午11.22.48.png

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

3.包裝類(lèi)02_細(xì)節(jié)

Math


截屏2021-02-26 下午2.34.38.png

4. Math_Random_UUID

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

5. 數(shù)字格式化_BigDecimal

截屏2021-02-26 下午3.07.32.png
截屏2021-02-26 下午3.07.43.png

高精度計(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ù)

截屏2021-02-26 下午3.18.48.png

使用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)信息。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容