最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java入門到精通的學(xué)習(xí)筆記:零基礎(chǔ)如何快速學(xué)會(huì)Java開發(fā)?

 更新時(shí)間:2026年07月25日 11:57:43   作者:渣渣盟  
想零基礎(chǔ)快速學(xué)會(huì)Java開發(fā)?這篇文章為你整理了從Java基礎(chǔ)語(yǔ)法、面向?qū)ο?、集合框架到多線程、反射等核心知識(shí)點(diǎn),還有IDEA開發(fā)技巧和實(shí)戰(zhàn)案例,幫你系統(tǒng)掌握J(rèn)ava開發(fā)必備技能,少走彎路

背景知識(shí)

Java 相關(guān)概念

  1. JavaSE (Java Standard Edition): 基礎(chǔ)版,用于開發(fā)桌面應(yīng)用程序。
  2. JavaEE (Java Enterprise Edition): 企業(yè)版,用于開發(fā)企業(yè)級(jí)應(yīng)用程序。
  3. JavaME (Java Micro Edition): 微型版,用于開發(fā)嵌入式系統(tǒng)和移動(dòng)設(shè)備應(yīng)用程序。

編譯與運(yùn)行

  1. 編譯階段:

    • 源文件: .java 文件。
    • 字節(jié)碼文件: .class 文件。
    • 編譯工具: javac.exe,用于將 .java 文件編譯為 .class 文件。
      • 命令: javac 文件名.java
      • 編譯包: javac -d 編譯后存放路徑 java源文件路徑
  2. 運(yùn)行階段:

    • 運(yùn)行工具: java.exe,用于運(yùn)行 .class 文件。
      • 命令: java 類名(不帶 .class 后綴)
    • JVM (Java Virtual Machine): Java 虛擬機(jī),負(fù)責(zé)執(zhí)行字節(jié)碼文件。

開發(fā)環(huán)境

  1. JDK (Java Development Kit): Java 開發(fā)工具包,包含編譯器、調(diào)試器等開發(fā)工具。
  2. JRE (Java Runtime Environment): Java 運(yùn)行環(huán)境,包含 JVM 和運(yùn)行 Java 程序所需的庫(kù)。
  3. JVM (Java Virtual Machine): Java 虛擬機(jī),負(fù)責(zé)執(zhí)行字節(jié)碼文件。

工具與格式

  1. native2ascii: 用于將 Unicode 字符轉(zhuǎn)換為 \u 表示的 ASCII 格式。
  2. UML (Unified Modeling Language): 面向?qū)ο笤O(shè)計(jì)圖,用于表示類、接口、繼承、實(shí)現(xiàn)等關(guān)系。
    • 空心箭頭: 指向父類(繼承)。
    • 空心虛線箭頭: 指向接口(實(shí)現(xiàn))。
    • 實(shí)心實(shí)線箭頭: 表示關(guān)聯(lián)關(guān)系。

注釋

  1. 單行注釋: //
  2. 多行注釋: /* */
  3. 文檔注釋: /** */,用于生成幫助文檔。

類與方法結(jié)構(gòu)

類體 {
    方法體 {
        java語(yǔ)句;
    }
}

總結(jié)

  • JavaSE 是基礎(chǔ)版,JavaEE 是企業(yè)版,JavaME 是微型版。
  • 編譯 使用 javac,運(yùn)行 使用 java。
  • JDK 是開發(fā)工具包,JRE 是運(yùn)行環(huán)境,JVM 是虛擬機(jī)。
  • UML 用于面向?qū)ο笤O(shè)計(jì),注釋 用于代碼說(shuō)明。
  • 類與方法 的基本結(jié)構(gòu)如上所示。

Java SE API 和文檔

一、集成開發(fā)環(huán)境(IDEA)

以下是用戶提供的快捷鍵和組織方式的總結(jié):

組織方式

  1. Project(工程): 最高層級(jí),包含多個(gè)模塊。
  2. Module(模塊): 工程下的子模塊,包含多個(gè)包。
  3. Package(包): 模塊下的子包,用于組織類和資源。

字體設(shè)置

  • 路徑: File -> Settings -> Font
    用于調(diào)整編輯器的字體樣式和大小。

快捷鍵分類總結(jié)

導(dǎo)航與操作

  1. 展開/移動(dòng)列表:

    • 左右箭頭: 展開或折疊列表。
    • 上下箭頭: 在列表中移動(dòng)。
  2. 切換與定位:

    • Alt+左右箭頭: 切換 Java 程序。
    • Alt+上下箭頭: 在方法間快速移動(dòng)。
    • Alt+標(biāo)號(hào): 打開標(biāo)號(hào)窗口。
    • Ctrl+G: 定位到文件的某一行。
    • Ctrl+點(diǎn)擊: 切換源碼。
    • Ctrl+H: 查看實(shí)現(xiàn)類。
  3. 查找與搜索:

    • Ctrl+Shift+N: 查找文件。
    • Ctrl+N: 查找類文件。
    • Ctrl+F12: 在當(dāng)前類中查找一個(gè)方法。

編輯與格式化

  1. 代碼編輯:

    • Ctrl+Y: 刪除一行。
    • Shift+F6: 重命名。
    • Alt+拖動(dòng): 一次編輯多行。
    • Ctrl+Alt+T: 將選中的代碼放在 TRY{}、IF{}、ELSE{} 中。
  2. 代碼提示與自動(dòng)補(bǔ)全:

    • Ctrl+空格: 代碼提示。
    • Ctrl+P: 方法參數(shù)提示。
    • Ctrl+J: 自動(dòng)代碼。
    • Ctrl+Alt+Space: 類名或接口名提示。
  3. 格式化與優(yōu)化:

    • Ctrl+Alt+L: 格式化代碼。
    • Ctrl+Alt+I: 自動(dòng)縮進(jìn)。
    • Ctrl+Alt+O: 優(yōu)化導(dǎo)入的類和包。

運(yùn)行與糾錯(cuò)

  1. 運(yùn)行程序:

    • Ctrl+Shift+F10: 運(yùn)行當(dāng)前程序。
  2. 糾錯(cuò)與提示:

    • Alt+回車: 糾錯(cuò)提示。

窗口操作

  1. 全屏模式:
    • Ctrl+Shift+F12: 切換全屏模式。

總結(jié)

  • 組織方式: 工程 -> 模塊 -> 包,層級(jí)清晰,便于管理。
  • 快捷鍵:
    • 導(dǎo)航與查找:快速定位文件、類、方法。
    • 編輯與格式化:提高代碼編寫效率。
    • 運(yùn)行與糾錯(cuò):快速運(yùn)行程序并修復(fù)錯(cuò)誤。
    • 窗口操作:優(yōu)化開發(fā)環(huán)境布局。

二、JVM內(nèi)存劃分

局部變量在方法體中聲明,運(yùn)行階段內(nèi)存在棧中分配

方法區(qū)內(nèi)存:字節(jié)碼文件在加載 的時(shí)候?qū)⑵浞旁诜椒▍^(qū)之中(最先有數(shù)據(jù),調(diào)用方法時(shí)在棧內(nèi)分配空間)

堆內(nèi)存(heap):new對(duì)象(成員變量中的實(shí)例變量(一個(gè)對(duì)象一份)在java對(duì)象內(nèi)部存儲(chǔ)),只能通過(guò)引用調(diào)用操作

棧(stack)內(nèi)存:棧幀永遠(yuǎn)指向棧頂元素,棧頂元素處于活躍狀態(tài),先進(jìn)后出,后進(jìn)先出(存儲(chǔ)局部變量)

內(nèi)存區(qū)域與數(shù)據(jù)存儲(chǔ)

  1. 堆內(nèi)存(Heap):

    • 存儲(chǔ)實(shí)例變量(對(duì)象屬性)。
    • 每個(gè) JVM 實(shí)例只有一個(gè)堆內(nèi)存,所有線程共享。
    • 垃圾回收器(GC)主要針對(duì)堆內(nèi)存進(jìn)行回收。
  2. 方法區(qū)(Method Area):

    • 存儲(chǔ)靜態(tài)變量(類變量)和類元數(shù)據(jù)(如類信息、常量池等)。
    • 每個(gè) JVM 實(shí)例只有一個(gè)方法區(qū),所有線程共享。
    • 方法區(qū)是最先有數(shù)據(jù)的內(nèi)存區(qū)域,因?yàn)轭惣虞d時(shí)靜態(tài)變量和類信息會(huì)初始化。
  3. 棧內(nèi)存(Stack):

    • 存儲(chǔ)局部變量和方法調(diào)用棧幀。
    • 每個(gè)線程有一個(gè)獨(dú)立的棧內(nèi)存,線程私有。
    • 棧內(nèi)存是使用最頻繁的內(nèi)存區(qū)域,因?yàn)榉椒ㄕ{(diào)用和局部變量的生命周期較短。

變量存儲(chǔ)位置

  1. 局部變量:

    • 存儲(chǔ)在棧內(nèi)存中。
    • 生命周期與方法調(diào)用一致,方法結(jié)束時(shí)局部變量會(huì)被銷毀。
  2. 實(shí)例變量:

    • 存儲(chǔ)在堆內(nèi)存中。
    • 生命周期與對(duì)象一致,對(duì)象被垃圾回收時(shí)實(shí)例變量會(huì)被銷毀。
  3. 靜態(tài)變量:

    • 存儲(chǔ)在方法區(qū)中。
    • 生命周期與類一致,類卸載時(shí)靜態(tài)變量會(huì)被銷毀。

垃圾回收器(GC)

  1. 主要目標(biāo):

    • 垃圾回收器主要針對(duì)堆內(nèi)存進(jìn)行回收,清理不再使用的對(duì)象。
    • 棧內(nèi)存和方法區(qū)的垃圾回收機(jī)制與堆內(nèi)存不同。
  2. 特點(diǎn):

    • 堆內(nèi)存是垃圾回收的主要區(qū)域,因?yàn)閷?duì)象生命周期較長(zhǎng)且占用內(nèi)存較大。
    • 棧內(nèi)存和方法區(qū)的垃圾回收效率較高,因?yàn)樗鼈兊纳芷谳^短且數(shù)據(jù)量相對(duì)較小。

三、關(guān)鍵字:

類與關(guān)鍵字

  1. public:

    • 表示公開的類,類名必須與文件名一致,且一個(gè)文件中只能有一個(gè) public 類。
  2. class:

    • 用于定義一個(gè)類。
  3. static:

    • 表示靜態(tài)的,修飾的成員變量或方法屬于類級(jí)別,不依賴于對(duì)象。
    • 靜態(tài)變量在類加載時(shí)初始化,存儲(chǔ)在方法區(qū)內(nèi)存中。
    • 靜態(tài)方法不能訪問(wèn)實(shí)例變量或?qū)嵗椒?,需要通過(guò)對(duì)象訪問(wèn)。
  4. break:

    • 用于跳出循環(huán)或 switch 語(yǔ)句。
  5. continue:

    • 用于跳過(guò)當(dāng)前循環(huán)的剩余部分,直接進(jìn)入下一次循環(huán)。
    • 語(yǔ)法:continue 循環(huán)名稱;循環(huán)名稱:
  6. this:

    • 表示當(dāng)前對(duì)象的引用。
    • 用于區(qū)分局部變量和實(shí)例變量,或在構(gòu)造方法中調(diào)用其他構(gòu)造方法(this(實(shí)參))。
    • 不能用于靜態(tài)方法中。
  7. native:

    • 用于調(diào)用 JVM 本地程序。

輸入與輸出

  1. System.out.println():

    • 控制臺(tái)輸出,println 表示輸出并換行。
  2. 鍵盤輸入:

    • 創(chuàng)建鍵盤掃描器對(duì)象:java.util.Scanner s = new java.util.Scanner(System.in);
    • 字符串輸入:String user = s.next();
    • 整數(shù)輸入:int num = s.nextInt();

final關(guān)鍵字

  1. 修飾類:

    • 類不能被繼承。
  2. 修飾方法:

    • 方法不能被重寫。
  3. 修飾變量:

    • 變量不能被修改。
    • 修飾的成員變量必須手動(dòng)賦值。
    • 修飾的引用一旦指向一個(gè)對(duì)象,就不能指向其他對(duì)象,但所指向的內(nèi)存可以修改。
  4. 常量:

    • 定義常量:public static final 類型 常量名 = 值;
    • 命名規(guī)則:全部大寫,用下劃線分隔。

super關(guān)鍵字

  1. 作用:

    • 代表當(dāng)前對(duì)象的父類型特征。
    • 用于訪問(wèn)父類的屬性、方法或調(diào)用父類的構(gòu)造方法。
  2. 語(yǔ)法:

    • 訪問(wèn)父類屬性或方法:super.
    • 調(diào)用父類構(gòu)造方法:super()
  3. 規(guī)則:

    • 不能用于靜態(tài)方法中。
    • 如果父類和子類有同名屬性,訪問(wèn)父類屬性時(shí)不能省略 super。
    • 構(gòu)造方法的第一行如果沒(méi)有 this()super(),默認(rèn)會(huì)調(diào)用 super()

static關(guān)鍵字

  1. 靜態(tài)變量:

    • 屬于類級(jí)別,不依賴于對(duì)象,類加載時(shí)初始化。
  2. 靜態(tài)方法:

    • 類級(jí)別的方法,不能訪問(wèn)實(shí)例變量或?qū)嵗椒ā?/li>
  3. 靜態(tài)代碼塊:

    • 在類加載時(shí)執(zhí)行,只執(zhí)行一次。
    • 語(yǔ)法:static {}
  4. 實(shí)例代碼塊:

    • 在構(gòu)造方法執(zhí)行之前執(zhí)行,用于對(duì)象初始化。

包與導(dǎo)入

  1. package:

    • 用于管理類,命名規(guī)則:公司域名倒序.項(xiàng)目名.模塊名.功能名。
    • 語(yǔ)法:package 包名;
  2. import:

    • 用于導(dǎo)入包中的類。
    • 語(yǔ)法:import 包名.類名;import 包名.*;
    • java.lang.* 是核心語(yǔ)言包,無(wú)需導(dǎo)入。
  3. 快捷鍵:

    • Ctrl+Shift+O:自動(dòng)導(dǎo)入。

訪問(wèn)控制權(quán)限修飾符

  1. private:

    • 私有訪問(wèn)權(quán)限,只能在本類中訪問(wèn)。
  2. default:

    • 默認(rèn)訪問(wèn)權(quán)限,可以被本包中的其他類訪問(wèn)。
  3. protected:

    • 受保護(hù)的訪問(wèn)權(quán)限,可以被本包及不同包的子類訪問(wèn)。
  4. public:

    • 公共訪問(wèn)權(quán)限,可以在任何地方訪問(wèn)。
  5. 類的修飾符:

    • 類只能使用 public 或默認(rèn)修飾符(缺?。?,內(nèi)部類除外。

總結(jié)

  • 類與關(guān)鍵字public、classstatic、this、super 等關(guān)鍵字的作用與用法。
  • 輸入與輸出:控制臺(tái)輸出與鍵盤輸入的基本操作。
  • final:用于修飾類、方法、變量,表示不可修改。
  • static:修飾類級(jí)別的成員,與對(duì)象無(wú)關(guān)。
  • 包與導(dǎo)入packageimport 的使用及命名規(guī)則。
  • 訪問(wèn)控制權(quán)限privatedefault、protectedpublic 的訪問(wèn)范圍。

四、Java基礎(chǔ)

以下是用戶提供的內(nèi)容的總結(jié):

標(biāo)識(shí)符

  1. 定義:

    • 用戶有權(quán)命名的單詞,包括類名、方法名、常量名、變量名、接口名等。
  2. 命名規(guī)則:

    • 類名、接口名: 首字母大寫,后面每個(gè)單詞首字母大寫(大駝峰命名法)。
    • 方法名、變量名: 首字母小寫,后面每個(gè)單詞首字母大寫(小駝峰命名法)。
    • 常量名: 全部大寫,單詞間用下劃線分隔。

字面值

  • 定義: 數(shù)據(jù)本身,如數(shù)字、字符串等,通常以紫色顯示。

變量

  1. 局部變量:

    • 定義在方法體內(nèi),沒(méi)有默認(rèn)值,必須手動(dòng)初始化。
    • 生命周期與方法調(diào)用一致。
  2. 成員變量:

    • 定義在類體內(nèi),有默認(rèn)值(數(shù)值類型為 0,布爾類型為 false,引用類型為 null)。
    • 分為實(shí)例變量和靜態(tài)變量。
  3. 實(shí)例變量:

    • 不帶 static 關(guān)鍵字,屬于對(duì)象級(jí)別。
    • 必須通過(guò)對(duì)象引用訪問(wèn)(引用.變量名)。
    • 存儲(chǔ)在堆內(nèi)存中。
  4. 靜態(tài)變量:

    • static 關(guān)鍵字,屬于類級(jí)別。
    • 在類加載時(shí)初始化,存儲(chǔ)在方法區(qū)內(nèi)存中。
    • 通過(guò)類名訪問(wèn)(類名.變量名)。

引用

  • 定義: 是一個(gè)變量,可以是實(shí)例變量或局部變量。
    • 實(shí)例變量: 類名 引用 = new 類名();
    • 局部變量: 引用 變量名 = new 引用();

數(shù)據(jù)類型

  1. 基本數(shù)據(jù)類型:

    • 整數(shù)型: byte(1 字節(jié))、short(2 字節(jié))、int(4 字節(jié))、long(8 字節(jié),后綴 L)。
    • 浮點(diǎn)型: float(4 字節(jié))、double(8 字節(jié))。
    • 布爾型: boolean(1 字節(jié))。
    • 字符型: char(2 字節(jié))。
  2. 引用數(shù)據(jù)類型:

    • 字符串: String,不可變,存儲(chǔ)在方法區(qū)字符串池中。
  3. 比較:

    • 基本數(shù)據(jù)類型使用 == 判斷相等。
    • 引用數(shù)據(jù)類型(包括 String)使用 equals 判斷相等。

字符編碼

  • 發(fā)展順序: ASCII < ISO-8859-1 < GB2312 < GBK < GB18030 < Big5 < Unicode(統(tǒng)一全球編碼)。

位運(yùn)算符

  1. 邏輯異或(^): 兩邊不一樣為真。
  2. 短路與(&&): 左邊為假時(shí)直接返回假。
  3. 按位與(&): 將操作數(shù)轉(zhuǎn)換為二進(jìn)制后按位與。
  4. 短路或(||): 左邊為真時(shí)直接返回真。
  5. 左移(<<): 二進(jìn)制數(shù)據(jù)左移,相當(dāng)于乘以 2 的 N 次方。
  6. 右移:
    • 帶符號(hào)右移(>>): 正數(shù)用 0 填充,負(fù)數(shù)用 1 填充。
    • 無(wú)符號(hào)右移(>>>): 無(wú)論正負(fù)都用 0 填充。
  7. 按位取反(~): 將二進(jìn)制每一位取反,結(jié)果為 -(n+1)

方法(函數(shù))

  1. 定義:

    [修飾符列表] 返回值類型 方法名(形參列表) {
        方法體;
        return; // return 后不能跟語(yǔ)句
    }
    
  2. 調(diào)用: 類名.方法名(實(shí)參列表);

  3. 實(shí)例方法: 不帶 static,需要對(duì)象參與。

  4. 靜態(tài)方法: 帶 static,與對(duì)象無(wú)關(guān)。

方法重載(Overload)

  • 定義: 在同一類中,方法名相同但參數(shù)列表不同。
  • 特點(diǎn): 與返回值類型和修飾符列表無(wú)關(guān)。

方法遞歸

  • 定義: 方法調(diào)用自身,每次遞歸都會(huì)分配新的內(nèi)存空間(壓棧)。

  • 示例:

    public static int sum(int n) {
        if (n == 1) {
            return 1;
        }
        return n + sum(n - 1);
    }
    

方法覆蓋(Override)

  1. 定義: 發(fā)生在繼承關(guān)系中,子類重寫父類的方法。
  2. 規(guī)則:
    • 方法名、返回值類型、形參列表必須與父類一致。
    • 訪問(wèn)權(quán)限不能比父類更低,拋出異常不能更多。
  3. 限制:
    • 私有方法、構(gòu)造方法不能覆蓋。
    • 靜態(tài)方法不存在覆蓋。

總結(jié)

  • 標(biāo)識(shí)符: 命名規(guī)則與用途。
  • 變量: 局部變量、實(shí)例變量、靜態(tài)變量的定義與存儲(chǔ)位置。
  • 數(shù)據(jù)類型: 基本數(shù)據(jù)類型與引用數(shù)據(jù)類型的區(qū)別。
  • 位運(yùn)算符: 各種位運(yùn)算符的作用與用法。
  • 方法: 定義、調(diào)用、重載、遞歸與覆蓋的規(guī)則與特點(diǎn)。

五、Java 控制流與 Lambda 表達(dá)式

1.控制流語(yǔ)句

  • If-Else 語(yǔ)句

    if (條件) {
        // 語(yǔ)句
    } else if (表達(dá)式) {
        // 語(yǔ)句
    } else {
        // 語(yǔ)句
    }
    
  • Switch 語(yǔ)句

    switch (關(guān)鍵詞) {
        case 關(guān)鍵詞:
            // java語(yǔ)句
            break;
        default:
            // 默認(rèn)語(yǔ)句
    }
    
  • For 循環(huán)

    for (初始表達(dá)式; 布爾表達(dá)式; 更新循環(huán)體) {
        // 循環(huán)體
    }
    
  • 增強(qiáng) For 循環(huán)(For Each)

    for (元素類型 變量名 : 數(shù)組或集合) {
        System.out.println(變量名);
    }
    
  • While 循環(huán)

    while (表達(dá)式) {
        // 循環(huán)體
    }
    
  • Do-While 循環(huán)

    do {
        // 循環(huán)體
    } while (布爾表達(dá)式);
    

2.Java 標(biāo)簽

  • 標(biāo)簽用于控制嵌套循環(huán)的跳轉(zhuǎn)和中斷。
  • 語(yǔ)法label:
  • 用法
    • continue label;:跳過(guò)當(dāng)前循環(huán),繼續(xù)執(zhí)行標(biāo)簽處的循環(huán)。
    • break label;:結(jié)束標(biāo)簽處的循環(huán),執(zhí)行循環(huán)后的代碼。

3.Lambda 表達(dá)式

  • 實(shí)現(xiàn) Runnable

    // Java 8 之前
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Before Java8, too much code for too little to do");
        }
    }).start();
    
    // Java 8 方式
    new Thread(() -> System.out.println("In Java8, Lambda expression rocks !!")).start();
    
  • 事件處理

    // Java 8 之前
    JButton show = new JButton("Show");
    show.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Event handling without lambda expression is boring");
        }
    });
    
    // Java 8 方式
    show.addActionListener((e) -> {
        System.out.println("Light, Camera, Action !! Lambda expressions Rocks");
    });
    
  • 列表迭代

    // Java 8 之前
    List<String> features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
    for (String feature : features) {
        System.out.println(feature);
    }
    
    // Java 8 之后
    features.forEach(n -> System.out.println(n));
    // 使用方法引用
    features.forEach(System.out::println);
    
  • Map 和 Reduce

    // 不使用 lambda 表達(dá)式
    List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
    for (Integer cost : costBeforeTax) {
        double price = cost + .12 * cost;
        System.out.println(price);
    }
    
    // 使用 lambda 表達(dá)式
    costBeforeTax.stream().map((cost) -> cost + .12 * cost).forEach(System.out::println);
    
    // 使用 reduce 計(jì)算總和
    double bill = costBeforeTax.stream().map((cost) -> cost + .12 * cost).reduce((sum, cost) -> sum + cost).get();
    System.out.println("Total : " + bill);
    
  • 對(duì)列表的每個(gè)元素應(yīng)用函數(shù)

    List<String> G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.", "Canada");
    String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", "));
    System.out.println(G7Countries);
    
  • 計(jì)算集合元素的最大值、最小值、總和以及平均值

    List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
    IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
    System.out.println("Highest prime number in List : " + stats.getMax());
    System.out.println("Lowest prime number in List : " + stats.getMin());
    System.out.println("Sum of all prime numbers : " + stats.getSum());
    System.out.println("Average of all prime numbers : " + stats.getAverage());
    

總結(jié)

  • 控制流語(yǔ)句:用于控制程序的執(zhí)行流程,包括條件判斷、循環(huán)等。
  • Java 標(biāo)簽:用于控制嵌套循環(huán)的跳轉(zhuǎn)和中斷。
  • Lambda 表達(dá)式:簡(jiǎn)化了匿名類的使用,使代碼更簡(jiǎn)潔,特別是在實(shí)現(xiàn)函數(shù)式接口(如 Runnable、ActionListener)時(shí)非常有用。
  • Stream API:提供了強(qiáng)大的集合操作功能,如 map、reduceforEach 等,使得對(duì)集合的處理更加高效和簡(jiǎn)潔。

六、面向?qū)ο?/h2>

面向過(guò)程與面向?qū)ο蟮膶?duì)比

  1. 面向過(guò)程

    • 因果關(guān)系:關(guān)注問(wèn)題的具體步驟和流程。
    • 具體過(guò)程:強(qiáng)調(diào)如何一步步解決問(wèn)題。
    • 耦合度高:各個(gè)模塊之間依賴性強(qiáng),修改一個(gè)模塊可能會(huì)影響其他模塊。
    • 軟件拓展性差:由于耦合度高,系統(tǒng)的擴(kuò)展和維護(hù)較為困難。
  2. 面向?qū)ο?/strong>:

    • 分類對(duì)象:將問(wèn)題分解為多個(gè)對(duì)象,每個(gè)對(duì)象負(fù)責(zé)特定的功能。
    • 關(guān)系層度低:對(duì)象之間的依賴關(guān)系較弱,耦合度低。
    • 關(guān)注對(duì)象功能:關(guān)注對(duì)象能完成哪些功能,而不是具體的實(shí)現(xiàn)步驟。
    • 三大特征
      • 封裝性:將復(fù)雜的事務(wù)封裝起來(lái),只保留簡(jiǎn)單的操作入口。封裝后形成獨(dú)立的對(duì)象,提高了代碼的復(fù)用性、適應(yīng)性和安全性。
      • 繼承性:實(shí)現(xiàn)代碼復(fù)用,最重要的是支持多態(tài)和方法覆蓋。
      • 多態(tài)性:父類型的引用可以指向子類型對(duì)象,降低程序耦合度,提高擴(kuò)展力。

面向?qū)ο蟮姆治雠c設(shè)計(jì)

  • 面向?qū)ο蟮姆治觯∣OA):分析問(wèn)題域,識(shí)別對(duì)象及其關(guān)系。
  • 面向?qū)ο蟮脑O(shè)計(jì)(OOD):設(shè)計(jì)對(duì)象的結(jié)構(gòu)和行為,定義類及其關(guān)系。
  • 面向?qū)ο蟮木幊蹋∣OP):使用編程語(yǔ)言實(shí)現(xiàn)設(shè)計(jì),創(chuàng)建對(duì)象并實(shí)現(xiàn)其功能。

類與對(duì)象

  • :高度抽象的對(duì)象的集合,是一個(gè)模板。
    • 靜態(tài)代碼塊:類加載時(shí)執(zhí)行。
    • 實(shí)例代碼塊:實(shí)例化時(shí)執(zhí)行。
    • 靜態(tài)變量:類級(jí)別的變量。
    • 實(shí)例變量:對(duì)象級(jí)別的變量,存儲(chǔ)在堆內(nèi)存中。
    • 構(gòu)造方法:創(chuàng)建對(duì)象時(shí)調(diào)用,用于初始化實(shí)例變量。
    • 靜態(tài)方法:類級(jí)別的方法。
    • 實(shí)例方法:對(duì)象級(jí)別的方法。
    • 成員變量:對(duì)象的屬性,描述對(duì)象的狀態(tài)。
    • 成員方法:對(duì)象的行為,描述對(duì)象的動(dòng)作。
  • 對(duì)象:類的具體實(shí)例。
    • 創(chuàng)建對(duì)象類名 對(duì)象名稱 = new 類名();
    • 使用對(duì)象對(duì)象名稱.屬性名對(duì)象名稱.方法名()
    • 修改對(duì)象引用.變量名 = 值
    • 引用與對(duì)象:引用保存了對(duì)象的地址,指向堆內(nèi)存中的對(duì)象。多個(gè)引用可以指向同一個(gè)對(duì)象,但一個(gè)引用只能指向一個(gè)對(duì)象。
User u=new User();
Address a=new Address();
u.addr=a;
Print(u.addr.city);
A.city=”天津”;
Print(u.addr.city);                                      

封裝

  • 私有化屬性:使用private關(guān)鍵字將屬性私有化。
  • 提供操作入口:通過(guò)gettersetter方法提供對(duì)屬性的訪問(wèn)和修改。
    • 讀取屬性public 數(shù)據(jù)類型 get屬性名() { return 屬性; }
    • 修改屬性public void set屬性名(數(shù)據(jù)類型 屬性) { this.屬性 = 屬性; }
  • 業(yè)務(wù)邏輯控制:在setter方法中添加業(yè)務(wù)邏輯進(jìn)行安全控制。

構(gòu)造方法

  • 作用:創(chuàng)建對(duì)象并初始化實(shí)例變量。
  • 語(yǔ)法修飾符 構(gòu)造方法名(形參) { 構(gòu)造方法體; this.實(shí)例變量 = 形參; }
  • 特點(diǎn):沒(méi)有返回值類型,方法名與類名一致,不能使用return返回值,但可以使用return結(jié)束方法。
  • 調(diào)用new 構(gòu)造方法名(實(shí)參)
  • 缺省構(gòu)造器:如果沒(méi)有定義構(gòu)造方法,編譯器會(huì)自動(dòng)生成一個(gè)無(wú)參的缺省構(gòu)造器。

繼承

  • 語(yǔ)法[修飾符列表] class 子類名 extends 父類名 { 類體 = 屬性 + 方法 }
  • 單繼承:Java中類只能繼承一個(gè)父類。
  • 繼承關(guān)系
    • 父類:也稱為基類、超類、superclass。
    • 子類:也稱為派生類、subclass。
  • 不可繼承:私有的屬性和方法、構(gòu)造方法。
  • 間接繼承:通過(guò)繼承鏈,子類可以間接繼承父類的父類。
  • 默認(rèn)繼承:如果沒(méi)有顯式繼承任何類,默認(rèn)繼承java.lang.Object類。
  • super關(guān)鍵字:用于調(diào)用父類的屬性、方法和構(gòu)造方法。

多態(tài)

  • 向上轉(zhuǎn)型(Upcasting):子類轉(zhuǎn)換為父類型,自動(dòng)類型轉(zhuǎn)換。
    • 語(yǔ)法父類 引用 = new 子類();
    • 特點(diǎn):編譯通過(guò),運(yùn)行沒(méi)有問(wèn)題。
  • 向下轉(zhuǎn)型(Downcasting):父類轉(zhuǎn)換為子類,強(qiáng)制類型轉(zhuǎn)換。
    • 語(yǔ)法子類 引用 = (子類) 父類引用;
    • 特點(diǎn):存在隱患,可能導(dǎo)致ClassCastException異常。
  • 動(dòng)態(tài)綁定:父類型引用指向子類型對(duì)象,調(diào)用方法時(shí)實(shí)際執(zhí)行的是子類的方法。
  • instanceof運(yùn)算符:用于在強(qiáng)制轉(zhuǎn)換前檢查對(duì)象的類型,避免ClassCastException異常。
    • 語(yǔ)法引用 instanceof 數(shù)據(jù)類型名
    • 返回值:布爾類型,true表示引用指向的對(duì)象是后面的數(shù)據(jù)類型,false表示不是。

以下是關(guān)于 抽象類接口 的總結(jié):

抽象類

  1. 定義:

    • 使用 abstract 關(guān)鍵字修飾的類,是類的進(jìn)一步抽象。
    • 屬于引用數(shù)據(jù)類型。
  2. 語(yǔ)法:

    [修飾符列表] abstract class 類名 {}
    
  3. 特點(diǎn):

    • 不能使用 privatefinal 修飾。
    • 抽象類可以包含抽象方法和非抽象方法。
    • 抽象類的子類可以是抽象類或非抽象類。
    • 不能實(shí)例化(不能創(chuàng)建對(duì)象),但可以有構(gòu)造方法,供子類使用。
  4. 抽象方法:

    • 使用 abstract 關(guān)鍵字修飾,無(wú)方法體。
    • 語(yǔ)法:[修飾符列表] abstract 返回值類型 方法名();
    • 包含抽象方法的類一定是抽象類。
  5. 規(guī)則:

    • 抽象類不一定有抽象方法,但抽象方法必須出現(xiàn)在抽象類中。
    • 非抽象類繼承抽象類時(shí),必須實(shí)現(xiàn)所有抽象方法。

接口

  1. 定義:

    • 使用 interface 關(guān)鍵字定義,是完全抽象的(特殊的抽象類)。
    • 屬于引用數(shù)據(jù)類型。
  2. 語(yǔ)法:

    [修飾符列表] interface 接口名 {}
    
  3. 特點(diǎn):

    • 接口中只能包含常量和抽象方法(默認(rèn) public static finalpublic abstract,修飾符可省略)。
    • 支持多繼承,一個(gè)接口可以繼承多個(gè)接口。
    • 接口不能繼承抽象類。
  4. 方法類型:

    • 抽象方法: abstract 修飾(可省略)。
    • 默認(rèn)方法: default 修飾,提供默認(rèn)實(shí)現(xiàn)。
    • 靜態(tài)方法: static 修飾,通過(guò)接口名調(diào)用。
  5. 實(shí)現(xiàn):

    • 類通過(guò) implements 關(guān)鍵字實(shí)現(xiàn)接口。
    • 非抽象類實(shí)現(xiàn)接口時(shí),必須重寫所有抽象方法。
    • 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口。
  6. 多態(tài):

    • 接口支持多態(tài):父類型引用指向子類對(duì)象。
    • 示例:接口名 引用 = new 實(shí)現(xiàn)類();
  7. 作用:

    • 解耦合:調(diào)用者面向接口調(diào)用,實(shí)現(xiàn)者面向接口編寫實(shí)現(xiàn)。
    • 擴(kuò)展性強(qiáng):接口+多態(tài)可以降低程序耦合度。

抽象類與接口的區(qū)別

特性抽象類接口
抽象程度半抽象(可以包含具體方法)完全抽象(只能包含抽象方法)
構(gòu)造方法有構(gòu)造方法,供子類使用無(wú)構(gòu)造方法
繼承單繼承(一個(gè)類只能繼承一個(gè)抽象類)支持多繼承(一個(gè)類可以實(shí)現(xiàn)多個(gè)接口)
內(nèi)容可以包含抽象方法和非抽象方法只能包含常量和抽象方法
用途抽象行為和數(shù)據(jù)主要抽象行為
實(shí)例化不能實(shí)例化不能實(shí)例化

開發(fā)中的選擇

  1. 抽象類:

    • 當(dāng)多個(gè)類有共同的屬性和行為,且需要部分具體實(shí)現(xiàn)時(shí)使用。
    • 適合定義“是什么”(is-a 關(guān)系)。
  2. 接口:

    • 當(dāng)需要定義一組行為規(guī)范,且不關(guān)心具體實(shí)現(xiàn)時(shí)使用。
    • 適合定義“能做什么”(like-a 關(guān)系)。

示例

  1. 抽象類:

    abstract class Animal {
        abstract void sound();
        void sleep() {
            System.out.println("Sleeping...");
        }
    }
    
  2. 接口:

    interface Flyable {
        void fly();
    }
    
  3. 實(shí)現(xiàn)與繼承:

    class Bird extends Animal implements Flyable {
        @Override
        void sound() {
            System.out.println("Chirp...");
        }
        @Override
        public void fly() {
            System.out.println("Flying...");
        }
    }
    

總結(jié)

  • 面向?qū)ο缶幊?/strong>通過(guò)封裝、繼承和多態(tài)三大特征,提高了代碼的復(fù)用性、擴(kuò)展性和維護(hù)性。

  • 類與對(duì)象是面向?qū)ο缶幊痰幕A(chǔ),類是對(duì)對(duì)象的抽象,對(duì)象是類的實(shí)例。

  • 封裝通過(guò)私有化屬性和提供操作入口,增強(qiáng)了代碼的安全性和可控性。

  • 繼承實(shí)現(xiàn)了代碼的復(fù)用,并支持多態(tài)和方法覆蓋。

  • 多態(tài)通過(guò)向上轉(zhuǎn)型和向下轉(zhuǎn)型,降低了程序的耦合度,提高了擴(kuò)展力。

  • 面向抽象編程,而不是面向具體,可以進(jìn)一步降低耦合度,提高系統(tǒng)的靈活性和可擴(kuò)展性。

  • 抽象類 用于定義類的共有特征,支持部分具體實(shí)現(xiàn)。

  • 接口 用于定義行為規(guī)范,支持多繼承和解耦合。

  • 在實(shí)際開發(fā)中,根據(jù)需求選擇抽象類或接口,合理使用可以提高代碼的擴(kuò)展性和可維護(hù)性。

七、類庫(kù)

源碼、字節(jié)碼與幫助文檔

  1. 源碼

    • 理解程序:源碼是程序員編寫的原始代碼,用于理解程序的邏輯和功能。
  2. 字節(jié)碼

    • 程序開發(fā)使用:字節(jié)碼是源碼編譯后的中間代碼,由JVM執(zhí)行。它是跨平臺(tái)的,可以在任何支持JVM的系統(tǒng)上運(yùn)行。
  3. 幫助文檔

    • 對(duì)開發(fā)提供幫助:幫助文檔是開發(fā)者的參考指南,通常通過(guò)javadoc生成。
    • 注意使用版本同一:確保使用的幫助文檔與代碼版本一致,避免因版本差異導(dǎo)致的錯(cuò)誤。

Object類(根類)

Object是Java中所有類的根類,提供了一些核心方法:

  1. protected Object clone()

    • 負(fù)責(zé)對(duì)象克隆,返回對(duì)象的副本。
  2. boolean equals(Object obj)

    • 判斷兩個(gè)對(duì)象是否相等。默認(rèn)比較引用地址,通常需要重寫以比較對(duì)象內(nèi)容。
  3. int hashCode()

    • 返回對(duì)象的哈希代碼值,用于哈希表等數(shù)據(jù)結(jié)構(gòu)。
  4. String toString()

    • 返回對(duì)象的字符串表示形式。默認(rèn)返回類名@哈希值,通常需要重寫以提供更有意義的信息。
  5. protected void finalize() throws Throwable

    • 垃圾回收器負(fù)責(zé)調(diào)用,用于對(duì)象銷毀前的清理工作。
  6. System.gc()

    • 建議啟動(dòng)垃圾回收器,但不保證立即執(zhí)行。

System類

System類提供了一些系統(tǒng)級(jí)別的操作:

  1. System.gc()

    • 建議啟動(dòng)垃圾回收器。
  2. System.out

    • 靜態(tài)變量,用于控制臺(tái)輸出。
  3. System.out.print()

    • 輸出打印不換行。
  4. System.out.println()

    • 換行輸出。
  5. System.currentTimeMillis()

    • 獲取自1970年1月1日00:00:00到當(dāng)前系統(tǒng)時(shí)間的總毫秒數(shù)。
  6. System.exit(0)

    • 退出JVM。

Arrays類

Arrays是數(shù)組工具類,提供了一些常用方法:

  1. Arrays.sort(arr)

    • 對(duì)數(shù)組進(jìn)行排序。
  2. Arrays.binarySearch(arr, key)

    • 使用二分法查找元素,不存在時(shí)返回-1。

String類

String類用于操作字符串,提供了豐富的構(gòu)造方法和方法:

  1. 構(gòu)造方法

    • String(byte[] byte):將字節(jié)數(shù)組轉(zhuǎn)換為字符串。
    • String(char[] char):將字符數(shù)組轉(zhuǎn)換為字符串。
    • String(String string):復(fù)制字符串。
  2. 常用方法

    • char charAt(int index):返回指定索引的字符。
    • int compareTo(String string):字典比較大小。
    • boolean contains(String string):判斷是否包含指定字符串。
    • boolean endsWith(String string):判斷是否以指定字符串結(jié)尾。
    • boolean startsWith(String prefix):判斷是否以指定前綴開頭。
    • boolean equals(Object anObject):比較字符串內(nèi)容。
    • boolean equalsIgnoreCase(String anotherString):忽略大小寫比較。
    • byte[] getBytes():將字符串轉(zhuǎn)換為字節(jié)數(shù)組。
    • int indexOf(String str):返回子字符串第一次出現(xiàn)的索引。
    • int lastIndexOf(String str):返回子字符串最后一次出現(xiàn)的索引。
    • boolean isEmpty():判斷字符串是否為空。
    • String replace(CharSequence target, CharSequence replacement):替換字符串。
    • String substring(int beginIndex):截取字符串。
    • char[] toCharArray():將字符串轉(zhuǎn)換為字符數(shù)組。
    • String toLowerCase():將字符串轉(zhuǎn)換為小寫。
    • String toUpperCase():將字符串轉(zhuǎn)換為大寫。
    • String[] split(String regex):按正則表達(dá)式拆分字符串。
    • String trim():去除前后空白。
    • static String valueOf():將其他類型轉(zhuǎn)換為字符串。

StringBuffer與StringBuilder

  1. StringBuffer

    • 線程安全,適用于多線程環(huán)境。
    • 常用方法:append()、reverse()
  2. StringBuilder

    • 非線程安全,性能優(yōu)于StringBuffer。

包裝類

包裝類用于將基本數(shù)據(jù)類型轉(zhuǎn)換為對(duì)象:

  1. 常用包裝類
    • Integer、Character等。
  2. 常用方法
    • int intValue():拆箱,將包裝類轉(zhuǎn)換為基本類型。
    • static int parseInt(String s):將字符串轉(zhuǎn)換為整數(shù)。

日期相關(guān)類

  1. java.util.Date

    • 表示日期和時(shí)間。
  2. SimpleDateFormat

    • 用于格式化日期。
    • 常用方法:format()parse()。

數(shù)字相關(guān)類

  1. DecimalFormat

    • 用于格式化數(shù)字。
  2. BigDecimal

    • 用于高精度計(jì)算,適用于財(cái)務(wù)數(shù)據(jù)。
  3. Random

    • 用于生成隨機(jī)數(shù)。

枚舉(Enum)

枚舉是一種特殊的類,用于定義一組常量:

enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

內(nèi)部類

  1. 成員內(nèi)部類

    • 定義在類中,可以訪問(wèn)外部類的所有成員。
  2. 局部?jī)?nèi)部類

    • 定義在方法中,只能在該方法內(nèi)訪問(wèn)。
  3. 靜態(tài)內(nèi)部類

    • 使用static修飾,只能訪問(wèn)外部類的靜態(tài)成員。
  4. 匿名內(nèi)部類

    • 沒(méi)有名稱的內(nèi)部類,通常用于實(shí)現(xiàn)接口或抽象類。

總結(jié)

  • 源碼是理解程序的基礎(chǔ),字節(jié)碼是程序運(yùn)行的關(guān)鍵,幫助文檔是開發(fā)的指南。
  • Object是Java的根類,提供了對(duì)象的基本操作。
  • System類提供了系統(tǒng)級(jí)別的操作,如垃圾回收、時(shí)間獲取等。
  • String類用于操作字符串,提供了豐富的構(gòu)造方法和方法。
  • StringBufferStringBuilder用于字符串的拼接和修改,前者線程安全,后者性能更優(yōu)。
  • 包裝類用于將基本數(shù)據(jù)類型轉(zhuǎn)換為對(duì)象。
  • 日期相關(guān)類用于處理日期和時(shí)間。
  • 內(nèi)部類提供了更靈活的代碼組織方式。

八、數(shù)組

一維數(shù)組

  1. 定義:

    • 數(shù)組是引用數(shù)據(jù)類型,存儲(chǔ)在堆內(nèi)存中。
    • 可以存儲(chǔ)各種數(shù)據(jù)類型,但不能直接存儲(chǔ)對(duì)象,存儲(chǔ)的是對(duì)象的引用(內(nèi)存地址)。
  2. 特點(diǎn):

    • 數(shù)組元素類型統(tǒng)一,最后一個(gè)下標(biāo)為 length - 1
    • 帶有 length 屬性,用于獲取數(shù)組長(zhǎng)度。
  3. 優(yōu)點(diǎn):

    • 查詢、查找、檢索某個(gè)下標(biāo)元素效率極高(內(nèi)存連續(xù),類型相同)。
  4. 缺點(diǎn):

    • 隨機(jī)增刪元素效率較低。
    • 不能存儲(chǔ)大數(shù)據(jù)量。
  5. 定義與初始化:

    • 靜態(tài)初始化:

      數(shù)據(jù)類型[] 數(shù)組名 = {元素1, 元素2, ...};
      
    • 動(dòng)態(tài)初始化:

      數(shù)據(jù)類型[] 數(shù)組名 = new 數(shù)據(jù)類型[長(zhǎng)度];
      
  6. 賦值:

    數(shù)組名[下標(biāo)] = 值;
    
  7. 遍歷:

    • 使用 for 循環(huán)或增強(qiáng) for 循環(huán):

      for (int i = 0; i < 數(shù)組名.length; i++) {
          System.out.println(數(shù)組名[i]);
      }
      
  8. 方法參數(shù):

    • 數(shù)組可以作為方法的參數(shù):

      void 方法名(數(shù)據(jù)類型[] 數(shù)組名) {}
      
  9. main 方法的數(shù)組參數(shù):

    • main 方法的參數(shù)是一個(gè)字符串?dāng)?shù)組,用于接收命令行參數(shù):

      public static void main(String[] args) {}
      
  10. 存儲(chǔ)對(duì)象:

    • 數(shù)組可以存儲(chǔ)對(duì)象的引用:

      類名[] 數(shù)組名 = new 類名[長(zhǎng)度];
      數(shù)組名[0] = new 類名();
      
  11. 數(shù)組擴(kuò)容:

    • 新建一個(gè)大數(shù)組,然后將原數(shù)組拷貝過(guò)去:

      int[] newArray = new int[原數(shù)組.length * 2];
      System.arraycopy(原數(shù)組, 0, newArray, 0, 原數(shù)組.length);
      
  12. 數(shù)組拷貝:

    • 使用 System.arraycopy 方法:

      System.arraycopy(原數(shù)組, 原起點(diǎn), 目標(biāo)數(shù)組, 目標(biāo)下標(biāo), 長(zhǎng)度);
      

二維數(shù)組

  1. 定義:

    • 二維數(shù)組是數(shù)組的數(shù)組,可以看作是一個(gè)表格。
  2. 語(yǔ)法:

    數(shù)據(jù)類型[][] 數(shù)組名 = new 數(shù)據(jù)類型[行數(shù)][列數(shù)];
    
  3. 初始化:

    • 靜態(tài)初始化:

      數(shù)據(jù)類型[][] 數(shù)組名 = {{元素1, 元素2}, {元素3, 元素4}};
      
    • 動(dòng)態(tài)初始化:

      數(shù)據(jù)類型[][] 數(shù)組名 = new 數(shù)據(jù)類型[行數(shù)][列數(shù)];
      
  4. 遍歷:

    • 使用嵌套 for 循環(huán):

      for (int i = 0; i < 數(shù)組名.length; i++) {
          for (int j = 0; j < 數(shù)組名[i].length; j++) {
              System.out.println(數(shù)組名[i][j]);
          }
      }
      

總結(jié)

  1. 一維數(shù)組:

    • 適用于存儲(chǔ)一組相同類型的數(shù)據(jù)。
    • 查詢效率高,增刪效率低。
    • 可以通過(guò) length 屬性獲取長(zhǎng)度。
    • 支持靜態(tài)初始化和動(dòng)態(tài)初始化。
  2. 二維數(shù)組:

    • 適用于存儲(chǔ)表格型數(shù)據(jù)。
    • 可以看作是一維數(shù)組的數(shù)組。
    • 支持靜態(tài)初始化和動(dòng)態(tài)初始化。
  3. 數(shù)組的優(yōu)缺點(diǎn):

    • 優(yōu)點(diǎn):查詢效率高,內(nèi)存連續(xù)。
    • 缺點(diǎn):增刪效率低,不能存儲(chǔ)大數(shù)據(jù)量。
  4. 數(shù)組的應(yīng)用場(chǎng)景:

    • 存儲(chǔ)一組固定長(zhǎng)度的數(shù)據(jù)。
    • 存儲(chǔ)對(duì)象引用。
    • 存儲(chǔ)表格型數(shù)據(jù)(二維數(shù)組)。

示例

  1. 一維數(shù)組:

    int[] arr = {1, 2, 3, 4, 5};
    for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
    
  2. 二維數(shù)組:

    int[][] arr = {{1, 2}, {3, 4}};
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr[i].length; j++) {
            System.out.println(arr[i][j]);
        }
    }
    
  3. 數(shù)組存儲(chǔ)對(duì)象:

    Animal[] animals = new Animal[2];
    animals[0] = new Cat();
    animals[1] = new Dog();
    
  4. 數(shù)組擴(kuò)容:

    int[] src = {1, 2, 3};
    int[] dest = new int[src.length * 2];
    System.arraycopy(src, 0, dest, 0, src.length);
    

通過(guò)合理使用數(shù)組,可以高效地存儲(chǔ)和操作數(shù)據(jù),但需要注意其增刪效率較低的缺點(diǎn)。

九、算法

以下是常見(jiàn) 排序算法查找算法 的思想總結(jié),并附帶 Java 實(shí)例:

排序算法

  1. 冒泡排序(Bubble Sort):

    • 思想:重復(fù)遍歷數(shù)組,每次比較相鄰元素,如果順序錯(cuò)誤則交換,直到?jīng)]有需要交換的元素。

    • 時(shí)間復(fù)雜度:O(n²)。

    • Java 實(shí)現(xiàn):

      public static void bubbleSort(int[] arr) {
          for (int i = 0; i < arr.length - 1; i++) {
              for (int j = 0; j < arr.length - 1 - i; j++) {
                  if (arr[j] > arr[j + 1]) {
                      int temp = arr[j];
                      arr[j] = arr[j + 1];
                      arr[j + 1] = temp;
                  }
              }
          }
      }
      
  2. 選擇排序(Selection Sort):

    • 思想:每次從未排序部分選擇最小元素,放到已排序部分的末尾。

    • 時(shí)間復(fù)雜度:O(n²)。

    • Java 實(shí)現(xiàn):

      public static void selectionSort(int[] arr) {
          for (int i = 0; i < arr.length - 1; i++) {
              int minIndex = i;
              for (int j = i + 1; j < arr.length; j++) {
                  if (arr[j] < arr[minIndex]) {
                      minIndex = j;
                  }
              }
              int temp = arr[i];
              arr[i] = arr[minIndex];
              arr[minIndex] = temp;
          }
      }
      
  3. 插入排序(Insertion Sort):

    • 思想:將未排序部分的元素逐個(gè)插入到已排序部分的正確位置。

    • 時(shí)間復(fù)雜度:O(n²)。

    • Java 實(shí)現(xiàn):

      public static void insertionSort(int[] arr) {
          for (int i = 1; i < arr.length; i++) {
              int key = arr[i];
              int j = i - 1;
              while (j >= 0 && arr[j] > key) {
                  arr[j + 1] = arr[j];
                  j--;
              }
              arr[j + 1] = key;
          }
      }
      
  4. 快速排序(Quick Sort):

    • 思想:選擇一個(gè)基準(zhǔn)元素,將數(shù)組分為兩部分,左邊小于基準(zhǔn),右邊大于基準(zhǔn),遞歸排序。

    • 時(shí)間復(fù)雜度:O(n log n)。

    • Java 實(shí)現(xiàn):

      public static void quickSort(int[] arr, int low, int high) {
          if (low < high) {
              int pivot = partition(arr, low, high);
              quickSort(arr, low, pivot - 1);
              quickSort(arr, pivot + 1, high);
          }
      }
      
      private static int partition(int[] arr, int low, int high) {
          int pivot = arr[high];
          int i = low - 1;
          for (int j = low; j < high; j++) {
              if (arr[j] < pivot) {
                  i++;
                  int temp = arr[i];
                  arr[i] = arr[j];
                  arr[j] = temp;
              }
          }
          int temp = arr[i + 1];
          arr[i + 1] = arr[high];
          arr[high] = temp;
          return i + 1;
      }
      
  5. 歸并排序(Merge Sort):

    • 思想:將數(shù)組分成兩半,分別排序,然后合并。

    • 時(shí)間復(fù)雜度:O(n log n)。

    • Java 實(shí)現(xiàn):

      public static void mergeSort(int[] arr, int left, int right) {
          if (left < right) {
              int mid = (left + right) / 2;
              mergeSort(arr, left, mid);
              mergeSort(arr, mid + 1, right);
              merge(arr, left, mid, right);
          }
      }
      
      private static void merge(int[] arr, int left, int mid, int right) {
          int[] temp = new int[right - left + 1];
          int i = left, j = mid + 1, k = 0;
          while (i <= mid && j <= right) {
              if (arr[i] <= arr[j]) {
                  temp[k++] = arr[i++];
              } else {
                  temp[k++] = arr[j++];
              }
          }
          while (i <= mid) {
              temp[k++] = arr[i++];
          }
          while (j <= right) {
              temp[k++] = arr[j++];
          }
          for (int p = 0; p < temp.length; p++) {
              arr[left + p] = temp[p];
          }
      }
      

查找算法

  1. 線性查找(Linear Search):

    • 思想:從頭到尾遍歷數(shù)組,逐個(gè)比較,找到目標(biāo)元素。

    • 時(shí)間復(fù)雜度:O(n)。

    • Java 實(shí)現(xiàn):

      public static int linearSearch(int[] arr, int target) {
          for (int i = 0; i < arr.length; i++) {
              if (arr[i] == target) {
                  return i;
              }
          }
          return -1;
      }
      
  2. 二分查找(Binary Search):

    • 思想:在有序數(shù)組中,每次取中間元素與目標(biāo)比較,縮小查找范圍。

    • 時(shí)間復(fù)雜度:O(log n)。

    • Java 實(shí)現(xiàn):

      public static int binarySearch(int[] arr, int target) {
          int left = 0, right = arr.length - 1;
          while (left <= right) {
              int mid = (left + right) / 2;
              if (arr[mid] == target) {
                  return mid;
              } else if (arr[mid] < target) {
                  left = mid + 1;
              } else {
                  right = mid - 1;
              }
          }
          return -1;
      }
      

總結(jié)

  1. 排序算法:

    • 冒泡排序:簡(jiǎn)單但效率低,適合小規(guī)模數(shù)據(jù)。
    • 選擇排序:每次選擇最小元素,適合小規(guī)模數(shù)據(jù)。
    • 插入排序:適合部分有序的數(shù)據(jù)。
    • 快速排序:高效,適合大規(guī)模數(shù)據(jù)。
    • 歸并排序:穩(wěn)定且高效,適合大規(guī)模數(shù)據(jù)。
  2. 查找算法:

    • 線性查找:適合無(wú)序數(shù)據(jù)。
    • 二分查找:適合有序數(shù)據(jù),效率高。
  3. 選擇依據(jù):

    • 數(shù)據(jù)規(guī)模、是否有序、穩(wěn)定性要求等。

示例

public class Main {
    public static void main(String[] args) {
        int[] arr = {5, 3, 8, 4, 2};
        bubbleSort(arr);
        System.out.println("冒泡排序結(jié)果: " + Arrays.toString(arr));

        int[] arr2 = {5, 3, 8, 4, 2};
        quickSort(arr2, 0, arr2.length - 1);
        System.out.println("快速排序結(jié)果: " + Arrays.toString(arr2));

        int target = 4;
        int index = binarySearch(arr2, target);
        System.out.println("二分查找結(jié)果: " + (index != -1 ? "找到,下標(biāo)為 " + index : "未找到"));
    }
}

輸出:

冒泡排序結(jié)果: [2, 3, 4, 5, 8]
快速排序結(jié)果: [2, 3, 4, 5, 8]
二分查找結(jié)果: 找到,下標(biāo)為 2

通過(guò)合理選擇排序和查找算法,可以高效地處理數(shù)據(jù)。

十、異常

1. 異常的基本概念

  • 異常在 Java 中以類的方式存在,每個(gè)異常類都可以創(chuàng)建異常對(duì)象。
  • 方法覆蓋規(guī)則:子類重寫父類方法時(shí),不能拋出比父類方法更高的異常(運(yùn)行時(shí)異常 RuntimeException 除外)。
  • 異常的分類
    • java.lang.Throwable:異常的父類,有兩個(gè)子類:
      • Error:錯(cuò)誤,通常是系統(tǒng)級(jí)錯(cuò)誤(如 OutOfMemoryError),不可處理,只能退出程序。
      • Exception:異常,所有異常都是在運(yùn)行階段發(fā)生的。
        • Exception 的直接子類:編譯時(shí)異常(受檢異常 CheckedException),需要在編寫程序時(shí)預(yù)處理。
        • RuntimeException:運(yùn)行時(shí)異常,通常由程序邏輯錯(cuò)誤引起,不需要顯式處理。

2. 常見(jiàn)運(yùn)行時(shí)異常

  • NullPointerException:空指針異常,嘗試訪問(wèn) null 對(duì)象的成員。
  • ArrayIndexOutOfBoundsException:數(shù)組下標(biāo)越界異常。
  • ClassCastException:類型轉(zhuǎn)換異常,嘗試將對(duì)象強(qiáng)制轉(zhuǎn)換為不兼容的類型。
  • NumberFormatException:數(shù)字轉(zhuǎn)換異常,嘗試將非數(shù)字字符串轉(zhuǎn)換為數(shù)字。

3. 異常處理方式

  1. throws 關(guān)鍵字

    • 在方法聲明位置使用,將異常拋給調(diào)用者處理。

    • 示例:

      public void readFile() throws IOException {
          // 可能拋出 IOException 的代碼
      }
      
  2. try-catch-finally 語(yǔ)句

    • 捕獲并處理異常。

    • 示例:

      try {
          // 可能拋出異常的代碼
      } catch (NullPointerException e) {
          System.out.println("空指針異常: " + e.getMessage());
      } catch (ArrayIndexOutOfBoundsException e) {
          System.out.println("數(shù)組下標(biāo)越界: " + e.getMessage());
      } finally {
          // 無(wú)論是否發(fā)生異常,都會(huì)執(zhí)行的代碼
          System.out.println("finally 塊執(zhí)行");
      }
      

4. 常用異常方法

  • getMessage():獲取異常的簡(jiǎn)單描述信息(通常是構(gòu)造方法的參數(shù))。
  • printStackTrace():打印異常的堆棧追蹤信息(異步線程中常用)。

5. 自定義異常

  • 步驟

    1. 編寫一個(gè)類繼承 Exception(受檢異常)或 RuntimeException(運(yùn)行時(shí)異常)。
    2. 提供兩個(gè)構(gòu)造方法:一個(gè)無(wú)參,一個(gè)有參。
    3. 使用 throw 手動(dòng)拋出異常。
  • 示例

    // 自定義異常類
    public class MyException extends Exception {
        public MyException() {
            super();
        }
    
        public MyException(String message) {
            super(message);
        }
    }
    
    // 使用自定義異常
    public class Test {
        public static void main(String[] args) {
            try {
                throw new MyException("自定義異常發(fā)生");
            } catch (MyException e) {
                System.out.println(e.getMessage());
            }
        }
    }
    

6. 異常處理的最佳實(shí)踐

  • 明確異常類型:捕獲具體異常,而不是直接捕獲 Exception。
  • 合理使用 finally:用于釋放資源(如關(guān)閉文件、數(shù)據(jù)庫(kù)連接等)。
  • 避免空指針異常:在使用對(duì)象前進(jìn)行 null 檢查。
  • 日志記錄:使用日志框架(如 Log4jSLF4J)記錄異常信息,便于排查問(wèn)題。

總結(jié)

  • 異常分類ErrorException,其中 Exception 分為編譯時(shí)異常和運(yùn)行時(shí)異常。
  • 處理方式throws 拋給調(diào)用者,try-catch-finally 捕獲并處理。
  • 自定義異常:繼承 ExceptionRuntimeException,提供構(gòu)造方法,使用 throw 拋出。
  • 最佳實(shí)踐:明確異常類型,合理使用 finally,避免空指針異常,記錄日志。

十一、I/O

I/O(輸入/輸出)概述

I/O(Input/Output)是指應(yīng)用程序與外部設(shè)備(如磁盤、網(wǎng)絡(luò)、鍵盤、顯示器等)之間的數(shù)據(jù)交互。Java通過(guò)java.io包提供了豐富的I/O類庫(kù),支持文件操作、字節(jié)流、字符流等功能。

File類

File類是java.io包中唯一代表磁盤文件本身的對(duì)象,用于操作文件和目錄。

構(gòu)造方法

  1. File(String path)

    • 根據(jù)路徑創(chuàng)建File對(duì)象。
  2. File(String parent, String child)

    • 根據(jù)父路徑和子路徑(包括文件名)創(chuàng)建File對(duì)象。
  3. File(File parent, String child)

    • 根據(jù)File對(duì)象表示的父路徑和子路徑創(chuàng)建File對(duì)象。

注意:路徑分隔符可以使用\\(Windows)或/(Unix/Linux)。

常用方法

  1. boolean exists()

    • 判斷文件或目錄是否存在。
  2. boolean delete()

    • 刪除文件或目錄。
  3. boolean createNewFile()

    • 如果文件不存在,則創(chuàng)建一個(gè)新文件。
  4. String getName()

    • 返回文件或目錄的名稱。
  5. String getPath()

    • 返回文件或目錄的路徑。
  6. String getAbsolutePath()

    • 返回文件或目錄的絕對(duì)路徑。
  7. boolean canRead()

    • 判斷文件是否可讀。
  8. boolean canWrite()

    • 判斷文件是否可寫。
  9. boolean isFile()

    • 判斷是否為文件。
  10. boolean isDirectory()

    • 判斷是否為目錄。
  11. long length()

    • 返回文件內(nèi)容的長(zhǎng)度(字節(jié)數(shù))。
  12. String[] list()

    • 返回目錄內(nèi)所有文件和子目錄的名稱。
  13. File[] listFiles()

    • 返回目錄內(nèi)所有文件和子目錄的File對(duì)象。
  14. createTempFile(String prefix, String suffix)

    • 創(chuàng)建臨時(shí)文件。
  15. deleteOnExit()

    • JVM退出時(shí)自動(dòng)刪除文件。

字節(jié)流

字節(jié)流用于處理二進(jìn)制數(shù)據(jù)(如圖片、音頻、視頻等),以字節(jié)為單位進(jìn)行讀寫操作。

字節(jié)輸入流(InputStream)

InputStream是字節(jié)輸入流的抽象類,用于從源(如文件、網(wǎng)絡(luò)等)讀取數(shù)據(jù)。

常用方法

  1. int read()

    • 逐個(gè)字節(jié)讀取,返回讀取的字節(jié)值(0-255),如果到達(dá)流末尾則返回-1。
  2. int read(byte[] b)

    • 將數(shù)據(jù)讀取到字節(jié)數(shù)組b中,返回實(shí)際讀取的字節(jié)數(shù)。
  3. int read(byte[] b, int off, int len)

    • 從偏移量off開始,讀取len個(gè)字節(jié)到數(shù)組b中,返回實(shí)際讀取的字節(jié)數(shù)。
  4. void close()

    • 關(guān)閉流,釋放資源。

字節(jié)輸出流(OutputStream)

OutputStream是字節(jié)輸出流的抽象類,用于將數(shù)據(jù)寫入目標(biāo)(如文件、網(wǎng)絡(luò)等)。

常用方法

  1. void write(int b)

    • 逐個(gè)字節(jié)寫入。
  2. void write(byte[] b)

    • 將字節(jié)數(shù)組b中的數(shù)據(jù)寫入。
  3. void write(byte[] b, int off, int len)

    • 從偏移量off開始,寫入len個(gè)字節(jié)。
  4. void flush()

    • 強(qiáng)制將緩沖區(qū)中的數(shù)據(jù)寫入目標(biāo)。
  5. void close()

    • 關(guān)閉流,釋放資源。

具體實(shí)現(xiàn)類

  1. FileInputStream

    • 用于從文件中讀取字節(jié)數(shù)據(jù)。
  2. FileOutputStream

    • 用于將字節(jié)數(shù)據(jù)寫入文件。

拓展總結(jié)

  1. 文件操作

    • 使用File類可以創(chuàng)建、刪除、重命名文件,判斷文件是否存在,查詢文件屬性等。
  2. 字節(jié)流

    • 字節(jié)流適用于處理二進(jìn)制數(shù)據(jù),InputStreamOutputStream是字節(jié)流的抽象基類。
    • FileInputStreamFileOutputStream是常用的字節(jié)流實(shí)現(xiàn)類,用于文件的讀寫操作。
  3. 流的使用注意事項(xiàng)

    • 使用流時(shí),務(wù)必在操作完成后調(diào)用close()方法關(guān)閉流,釋放系統(tǒng)資源。
    • 對(duì)于輸出流,可以調(diào)用flush()方法強(qiáng)制將緩沖區(qū)中的數(shù)據(jù)寫入目標(biāo)。
  4. 臨時(shí)文件

    • 使用createTempFile()方法可以創(chuàng)建臨時(shí)文件,deleteOnExit()方法可以確保JVM退出時(shí)自動(dòng)刪除臨時(shí)文件。
  5. 路徑處理

    • 路徑分隔符可以使用\\(Windows)或/(Unix/Linux),Java會(huì)自動(dòng)處理。
  6. 性能優(yōu)化

    • 對(duì)于大文件的讀寫,建議使用緩沖區(qū)(如BufferedInputStreamBufferedOutputStream)來(lái)提高性能。

示例代碼

文件操作

File file = new File("test.txt");
if (!file.exists()) {
    file.createNewFile(); // 創(chuàng)建文件
}
System.out.println("文件名稱: " + file.getName());
System.out.println("文件路徑: " + file.getAbsolutePath());
file.delete(); // 刪除文件

字節(jié)流讀寫

// 寫入文件
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
    fos.write("Hello, World!".getBytes());
    fos.flush();
}

// 讀取文件
try (FileInputStream fis = new FileInputStream("output.txt")) {
    byte[] buffer = new byte[1024];
    int len;
    while ((len = fis.read(buffer)) != -1) {
        System.out.println(new String(buffer, 0, len));
    }
}

通過(guò)掌握這些核心概念和類庫(kù),可以高效地處理文件操作和字節(jié)流讀寫。

字符流總結(jié)

字符流是Java I/O中用于處理文本數(shù)據(jù)的流,它以字符為單位進(jìn)行讀寫操作。與字節(jié)流不同,字符流專門用于處理字符數(shù)據(jù)(如文本文件),并且支持字符編碼(如UTF-8、GBK等),能夠正確處理多字節(jié)字符。

字符流概述

字符流的核心類是ReaderWriter,它們分別是字符輸入流和字符輸出流的抽象基類。字符流的主要特點(diǎn)包括:

  1. 以字符為單位
    • 字符流以字符為單位讀寫數(shù)據(jù),適合處理文本文件。
  2. 支持字符編碼
    • 字符流可以正確處理字符編碼,避免亂碼問(wèn)題。
  3. 高效讀寫
    • 字符流通常與緩沖區(qū)結(jié)合使用(如BufferedReaderBufferedWriter),提高讀寫效率。

字符輸入流(Reader)

Reader是字符輸入流的抽象類,用于從源(如文件、字符串等)讀取字符數(shù)據(jù)。

常用方法

  1. int read()

    • 讀取單個(gè)字符,返回字符的Unicode值(0-65535),如果到達(dá)流末尾則返回-1。
  2. int read(char[] cbuf)

    • 將字符數(shù)據(jù)讀取到字符數(shù)組cbuf中,返回實(shí)際讀取的字符數(shù)。
  3. int read(char[] cbuf, int off, int len)

    • 從偏移量off開始,讀取len個(gè)字符到數(shù)組cbuf中,返回實(shí)際讀取的字符數(shù)。
  4. void close()

    • 關(guān)閉流,釋放資源。

具體實(shí)現(xiàn)類

  1. FileReader

    • 用于從文件中讀取字符數(shù)據(jù)。
  2. BufferedReader

    • 帶有緩沖區(qū)的字符輸入流,提供readLine()方法逐行讀取文本。
  3. InputStreamReader

    • 將字節(jié)流轉(zhuǎn)換為字符流,支持指定字符編碼。

字符輸出流(Writer)

Writer是字符輸出流的抽象類,用于將字符數(shù)據(jù)寫入目標(biāo)(如文件、控制臺(tái)等)。

常用方法

  1. void write(int c)

    • 寫入單個(gè)字符。
  2. void write(char[] cbuf)

    • 寫入字符數(shù)組cbuf中的數(shù)據(jù)。
  3. void write(char[] cbuf, int off, int len)

    • 從偏移量off開始,寫入len個(gè)字符。
  4. void write(String str)

    • 寫入字符串str。
  5. void write(String str, int off, int len)

    • 從偏移量off開始,寫入len個(gè)字符。
  6. void flush()

    • 強(qiáng)制將緩沖區(qū)中的數(shù)據(jù)寫入目標(biāo)。
  7. void close()

    • 關(guān)閉流,釋放資源。

具體實(shí)現(xiàn)類

  1. FileWriter

    • 用于將字符數(shù)據(jù)寫入文件。
  2. BufferedWriter

    • 帶有緩沖區(qū)的字符輸出流,提供newLine()方法寫入換行符。
  3. OutputStreamWriter

    • 將字節(jié)流轉(zhuǎn)換為字符流,支持指定字符編碼。

字符流與字節(jié)流的區(qū)別

  1. 單位不同

    • 字節(jié)流以字節(jié)為單位,適合處理二進(jìn)制數(shù)據(jù)。
    • 字符流以字符為單位,適合處理文本數(shù)據(jù)。
  2. 編碼支持

    • 字節(jié)流不涉及字符編碼,直接處理字節(jié)數(shù)據(jù)。
    • 字符流支持字符編碼,能夠正確處理多字節(jié)字符。
  3. 性能優(yōu)化

    • 字符流通常與緩沖區(qū)結(jié)合使用,提高讀寫效率。

示例代碼

字符流讀寫文件

// 寫入文件
try (FileWriter fw = new FileWriter("output.txt");
     BufferedWriter bw = new BufferedWriter(fw)) {
    bw.write("Hello, World!");
    bw.newLine(); // 寫入換行符
    bw.write("This is a test.");
}

// 讀取文件
try (FileReader fr = new FileReader("output.txt");
     BufferedReader br = new BufferedReader(fr)) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
}

使用指定編碼讀寫文件

// 寫入文件(指定編碼為UTF-8)
try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("output.txt"), "UTF-8");
     BufferedWriter bw = new BufferedWriter(osw)) {
    bw.write("你好,世界!");
}

// 讀取文件(指定編碼為UTF-8)
try (InputStreamReader isr = new InputStreamReader(new FileInputStream("output.txt"), "UTF-8");
     BufferedReader br = new BufferedReader(isr)) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
}

總結(jié)

  1. 字符流適用場(chǎng)景

    • 處理文本文件、字符串等字符數(shù)據(jù)。
  2. 核心類

    • ReaderWriter是字符流的抽象基類。
    • FileReader、BufferedReader、FileWriter、BufferedWriter是常用的實(shí)現(xiàn)類。
  3. 字符編碼

    • 使用InputStreamReaderOutputStreamWriter可以指定字符編碼,避免亂碼問(wèn)題。
  4. 性能優(yōu)化

    • 使用BufferedReaderBufferedWriter可以提高讀寫效率。
  5. 流關(guān)閉

    • 使用try-with-resources語(yǔ)法確保流被正確關(guān)閉,釋放資源。

通過(guò)掌握字符流的核心概念和類庫(kù),可以高效地處理文本數(shù)據(jù)的讀寫操作。

十二、集合

集合是Java中用于存儲(chǔ)和管理一組對(duì)象的容器。它提供了一種更靈活、更高效的方式來(lái)操作數(shù)據(jù)集合。以下是集合的核心概念和總結(jié):

集合的特點(diǎn)

  1. 容器性質(zhì)

    • 集合是一個(gè)容器,可以容納其他類型的數(shù)據(jù)。
    • 集合不能直接存儲(chǔ)基本數(shù)據(jù)類型(如int、char等),也不能直接存儲(chǔ)對(duì)象,存儲(chǔ)的是Java對(duì)象的內(nèi)存地址(引用)。
  2. 數(shù)據(jù)結(jié)構(gòu)

    • 不同的集合對(duì)應(yīng)不同的數(shù)據(jù)結(jié)構(gòu)(如數(shù)組、鏈表、哈希表、二叉樹等)。
    • 使用不同的集合等同于使用了不同的數(shù)據(jù)結(jié)構(gòu)。
  3. 包位置

    • 所有的集合類都位于java.util包中。

集合的層次結(jié)構(gòu)

  1. 超級(jí)父接口:Iterable<T>

    • 所有集合都是可迭代的,即可以通過(guò)迭代器遍歷集合中的元素。
    • 方法:Iterator<T> iterator():返回集合的迭代器。
  2. 單個(gè)元素集合的父接口:Collection<E>

    • 表示存儲(chǔ)單個(gè)元素的集合的超級(jí)接口。
    • 子接口包括:List、Set、Queue等。
  3. 鍵值對(duì)集合的父接口:Map<K,V>

    • 表示存儲(chǔ)鍵值對(duì)的集合,獨(dú)立于Collection體系。

集合的實(shí)現(xiàn)類總結(jié)

1.List接口的實(shí)現(xiàn)類:

  • ArrayList
    • 底層是數(shù)組,查詢快,增刪慢。
    • 非線程安全。
  • LinkedList
    • 底層是雙向鏈表,增刪快,查詢慢。
    • 非線程安全。
  • Vector
    • 底層是數(shù)組,線程安全,但效率較低,使用較少。

2.Set接口的實(shí)現(xiàn)類:

  • HashSet
    • 底層是HashMap,元素存儲(chǔ)在HashMapkey部分。
    • 無(wú)序且不允許重復(fù)。
  • TreeSet
    • 底層是TreeMap,元素存儲(chǔ)在TreeMapkey部分。
    • 元素自動(dòng)按大小順序排序。

3.Map接口的實(shí)現(xiàn)類:

  • HashMap
    • 底層是哈希表,非線程安全。
    • 允許null鍵和null值。
  • Hashtable
    • 底層是哈希表,線程安全,但效率較低,使用較少。
    • 不允許null鍵和null值。
  • Properties
    • 底層是哈希表,線程安全。
    • keyvalue只能存儲(chǔ)字符串(String)。
  • TreeMap
    • 底層是二叉樹。
    • key自動(dòng)按照大小順序排序。

集合的選擇

  1. 需要存儲(chǔ)單個(gè)元素

    • 如果需要有序且允許重復(fù),使用List
      • 查詢多,增刪少:ArrayList。
      • 增刪多,查詢少:LinkedList。
    • 如果不需要重復(fù)元素,使用Set
      • 無(wú)序:HashSet
      • 有序:TreeSet。
  2. 需要存儲(chǔ)鍵值對(duì)

    • 非線程安全:HashMap。
    • 線程安全:HashtableProperties。
    • 需要排序:TreeMap
  3. 線程安全

    • 如果需要線程安全,可以使用VectorHashtableProperties,但效率較低。
    • 推薦使用Collections.synchronizedList()ConcurrentHashMap等并發(fā)集合。

總結(jié)

  1. 集合的核心

    • 集合是存儲(chǔ)和管理一組對(duì)象的容器,存儲(chǔ)的是對(duì)象的內(nèi)存地址。
    • 不同的集合對(duì)應(yīng)不同的數(shù)據(jù)結(jié)構(gòu),選擇合適的集合可以提高程序效率。
  2. 常用集合

    • List:有序且允許重復(fù),常用ArrayListLinkedList。
    • Set:無(wú)序且不允許重復(fù),常用HashSetTreeSet。
    • Map:存儲(chǔ)鍵值對(duì),常用HashMapTreeMapProperties。
  3. 線程安全

    • 線程安全的集合有VectorHashtableProperties,但效率較低。
    • 推薦使用并發(fā)集合(如ConcurrentHashMap)來(lái)實(shí)現(xiàn)線程安全。

通過(guò)掌握集合的核心概念和常用實(shí)現(xiàn)類,可以更高效地處理數(shù)據(jù)集合,并根據(jù)需求選擇合適的集合類型。

List 集合存儲(chǔ)元素的特點(diǎn):

有序可重復(fù)

有序:存進(jìn)去的順序和取出的順序相同,每一個(gè)元素都有下標(biāo)

可重復(fù):存進(jìn)去1,可以再存儲(chǔ)一個(gè)1

Set 集合存儲(chǔ)元素的特點(diǎn)(Map的Key):

無(wú)序不可重復(fù)

無(wú)序:存進(jìn)去的順序和取出的順序不一定相同,另外 Set 集合中元素沒(méi)有下標(biāo)(哈希表的存儲(chǔ))

不可重復(fù):存進(jìn)去1,不能再存儲(chǔ)1了(哈希表的覆蓋)

SortedSet( SortedMap )集合存儲(chǔ)元素特點(diǎn):

首先是無(wú)序不可重復(fù)的,但是 SortedSet 集合中的元素是可排序的

無(wú)序:存進(jìn)去的順序和取出的順序不一定相同,另外 Set 集合中元素沒(méi)有下標(biāo)

不可重復(fù):存進(jìn)去1,不能再存儲(chǔ)1了

可排序:可以按照大小順序排列。

Map 集合的 key ,就是一個(gè) Set 集合。

往 Set 集合中放數(shù)據(jù),實(shí)際上放到了 Map 集合的 key 部分。

InterfaceCollection

沒(méi)有使用泛型前可以存儲(chǔ)Object的所有子類型

  • Boolean add(E e) 添加元素
  • Object[] toArray() 轉(zhuǎn)化成數(shù)組(使用不多)
  • Int size() 返回此集合中元素的數(shù)目。
  • Boolean contains(Object o) 如果此集合包含指定的元素(存放在集合中的類型,需要重寫equals方法)
  • Void clear() 從此集合中刪除所有元素
  • Boolean equals(Object o) 將指定的對(duì)象與此集合進(jìn)行比較以實(shí)現(xiàn)相等性(內(nèi)存地址)
  • Boolean remove(Object o) 從此集合中刪除指定元素的單個(gè)實(shí)例
  • Boolean isEmpty() 如果此集合不包含任何元素(判空)則返回。true

Iterator<E> iterator() ***:**不管存進(jìn)去什么,拿出來(lái)都是Object,取出來(lái)還是原類型

返回此集合中元素的迭代器**,Collection通用,Map集合不能用**

只要集合結(jié)構(gòu)發(fā)生改變迭代器一定要重新獲取

  • default void forEachRemaining(Consumer<? super E> action) 對(duì)每個(gè)剩余元素執(zhí)行給定的操作,直到所有元素都已處理完畢或該操作引發(fā)異常。
  • Boolean hasNext() 如果迭代具有更多元素,則返回。true
  • Object next() 返回迭代中的下一個(gè)元素。(返回object)
  • default void remove() 從基礎(chǔ)集合中刪除此迭代器返回的最后一個(gè)元素(可選操作)。

Interface List有序可重復(fù),Collection子接口

  • void add(int index, E element) 在此列表中的指定位置插入指定的元素
  • E get(int index) 返回此列表中指定位置處的元素
  • E set(int index, E element) 將此列表中指定位置的元素替換為指定的元素
  • int indexOf(Object o) 返回此列表中指定元素的第一次出現(xiàn)的索引,如果此列表不包含該元素,則返回 -1
  • int lastIndexOf(Object o) 返回此列表中指定元素的最后一次出現(xiàn)的索引,如果此列表不包含該元素,則返回 -1。
  • E remove(int index) 刪除此列表中指定位置的元素
Class ArrayList 非線程安全數(shù)組,初始化容量10,底層object數(shù)組

構(gòu)造方法:

  • ArrayList() 構(gòu)造初始容量為 10 的空列表(底層先創(chuàng)建了一個(gè)長(zhǎng)度為0的數(shù)組,添加元素是初始化為10,自動(dòng)擴(kuò)容1.5倍)
  • ArrayList(int initialCapacity) 構(gòu)造具有指定初始容量的空列表(建議提前估計(jì),減少擴(kuò)容)
  • ArrayList(Collection<? extends E> c) 構(gòu)造一個(gè)列表,其中包含指定集合的元素,并按集合的迭代器返回這些元素的順序排列。

方法:同List方法

Class LinkedList 雙向鏈表,隨機(jī)增刪效率高,檢索效率低
Class Vector 線程安全數(shù)組,默認(rèn)10,擴(kuò)容翻倍**(不經(jīng)常使用)**

轉(zhuǎn)換:使用集合工具類:java.util.Collections.synchronizedList(集合)

Interface Set無(wú)序不可重復(fù)存儲(chǔ)Map的Key

Class HashSet 哈希表(底層HashMap)

需要重寫hashCode和equals方法,其他方法參見(jiàn)HashMap

Interface SortedSet無(wú)序不可重復(fù)可排序

Class TreeSet 二叉樹(底層TreeMap Key部分)無(wú)序不可重復(fù)可排序

Key值自定義類需要實(shí)現(xiàn)java.long.Comparable接口或者創(chuàng)建比較器對(duì)象

class user implements Comparable<user>{      //自定義類需要實(shí)現(xiàn)接口
  int age;

  public user(int age) {
    this.age = age;
  }


 @Override
  public String toString() {
    return "user{" + "age=" + age + '}';
  }
  @Override         //重寫比較規(guī)則
  public int compareTo(user o) {
    return this.age-o.age;    //返回==0,value覆蓋,返回大于0 到右子樹,返回小于0到左子樹
  }
}

Interface Map<K,V>Map主接口(和Collection沒(méi)有繼承關(guān)系)

以Key和Value存儲(chǔ)數(shù)據(jù)都是引用數(shù)據(jù)類型,都存儲(chǔ)內(nèi)存地址,Key是主導(dǎo)

  • V put(K key, V value) 添加鍵值對(duì)(Key元素需要重新hashCode和equals方法)(Key可以為空,只有一個(gè))
  • void clear() 清空Map集合
  • V get(Object key) 通過(guò)key獲取value(key元素需要重新hashCode和equals方法)
  • boolean containsKey(Object key) 判斷Map是否包含某個(gè)key(底層equals)
  • boolean containsValue(Object value) 判斷Map是否包含某個(gè)value(底層equals)
  • boolean isEmpty() 判斷Map集合元素個(gè)數(shù)是否為零
  • Set<K> keySet() 獲取Map集合所有的Key(是個(gè)set集合)
  • V remove(Object key) 通過(guò)key刪除鍵值對(duì)
  • Collection<V> values() 獲取Map集合中鍵值對(duì)所有value(返回Collection)
  • int size() 獲取Map集合所有的鍵值對(duì)個(gè)數(shù)
Set<Map.Entry<Integer,String>>set1=m.entrySet();       //使用方法
Iterator<Map.Entry<Integer,String>> it=set1.iterator(); //獲取迭代器
while (it.hasNext()) {
  Map.Entry<Integer, String> entry = it.next();
  System.out.println(entry);     //直接遍歷
  Integer key = entry.getKey();    //獲取鍵
  String value = entry.getValue();    //獲取值
  System.out.println(key + "=" + value);   //分開遍歷

for(Map.Entry<Integer,String> node:set1)   //效率較高,適合大數(shù)據(jù),直接獲取
  System.out.println(node);     //組合遍歷
Class HashMap<K,V> 哈希表 非線程安全(初始化容量16[必須是2的倍數(shù)],默認(rèn)加載因子0.75)

Key元素類型需要重新hashCode和equals方法

JDK8新特性:當(dāng)單向鏈表長(zhǎng)度超過(guò)8后數(shù)據(jù)結(jié)構(gòu)會(huì)變成紅黑樹數(shù)據(jù)結(jié)構(gòu),當(dāng)紅黑樹小于6,會(huì)變回鏈表

構(gòu)造 函數(shù) 描述

  • HashMap() 使用默認(rèn)初始容量 (16) ,默認(rèn)負(fù)載系數(shù) (0.75)
  • HashMap(int initialCapacity) 指定的初始容量,默認(rèn)負(fù)載系數(shù) 初始容量必須是2的倍數(shù):達(dá)到散列均勻,提高存取效率
  • HashMap(int initialCapacity, float loadFactor) 指定初始容量和負(fù)載系數(shù)
  • HashMap(Map<? extends K,? extends V> m)
Class Hashtable<K,V> 哈希表 線程安全(synchronized) Key不可以為空*(不常用)**

初始化容量11,默認(rèn)加載因子0.75f,擴(kuò)容:原容量*2+1

Class Properties 屬性類 繼承Hashtable類 僅支持String

  • Object setProperty(String key, String value) 存
  • String getProperty(String key) 取
  • String getProperty(String key, String defaultValue) 當(dāng)key值為NULL時(shí),返回def的值;當(dāng)key值不為NULL時(shí),返回key的值

Interface SortedMap<K,V>

Class TreeMap<K,V> 二叉樹 可排序集合(中序遍歷)

Key值自定義類需要實(shí)現(xiàn)java.long.Comparable接口或者創(chuàng)建比較器對(duì)象(類或者匿名內(nèi)部類)

Class Collections 集合工具類
  • synchronizedMap(Map<K,V> m) 返回由指定映射支持的同步(線程安全)映射。
  • synchronizedList(List list) 返回由指定列表支持的同步(線程安全)列表。**
    **synchronizedCollection(Collection c) 返回由指定集合支持的同步(線程安全)集合
  • sort(List list, Comparator<? super T> c) 根據(jù)指定比較器引發(fā)的順序?qū)χ付斜磉M(jìn)行排序。

十三、泛型

1. 泛型概述

  • 引入時(shí)間:JDK 5.0 之后的新特性。

  • 作用

    • 統(tǒng)一集合中元素的類型,避免類型轉(zhuǎn)換錯(cuò)誤。
    • 只在程序編譯階段起作用,編譯后會(huì)進(jìn)行類型擦除(Type Erasure)。
  • 語(yǔ)法

    • 在創(chuàng)建對(duì)象時(shí),前后兩段添加泛型類型。

    • 示例:

      List<String> list = new ArrayList<String>();
      

2. 泛型的優(yōu)點(diǎn)

  • 類型安全:編譯時(shí)檢查類型,避免運(yùn)行時(shí)類型轉(zhuǎn)換錯(cuò)誤。
  • 代碼復(fù)用:可以編寫通用的類和方法,適用于多種類型。
  • 代碼簡(jiǎn)潔:減少?gòu)?qiáng)制類型轉(zhuǎn)換的代碼。

3. 泛型的缺點(diǎn)

  • 導(dǎo)致集合存儲(chǔ)缺少多樣性:泛型限制了集合中元素的類型,無(wú)法存儲(chǔ)多種類型的對(duì)象。
  • 類型擦除:泛型信息在編譯后會(huì)被擦除,運(yùn)行時(shí)無(wú)法獲取泛型的具體類型。

4. 自動(dòng)推斷機(jī)制(鉆石表達(dá)式)

  • 引入時(shí)間:JDK 7 新特性。

  • 作用:自動(dòng)推斷泛型類型,簡(jiǎn)化代碼。

  • 語(yǔ)法:只寫前面的泛型類型,后面的泛型類型可以省略。

  • 示例

    List<String> list = new ArrayList<>();
    

5. 自定義泛型

  • 泛型類

    • 在定義類時(shí)添加 <T>,T 是類型參數(shù)。

    • 示例:

      public class Box<T> {
          private T value;
      
          public void setValue(T value) {
              this.value = value;
          }
      
          public T getValue() {
              return value;
          }
      }
      
    • 使用:

      Box<String> box = new Box<>();
      box.setValue("Hello");
      String value = box.getValue();
      
  • 泛型方法

    • 在定義方法時(shí)添加 <T>,T 是類型參數(shù)。

    • 示例:

      public <T> void printArray(T[] array) {
          for (T element : array) {
              System.out.println(element);
          }
      }
      
    • 使用:

      Integer[] intArray = {1, 2, 3};
      printArray(intArray);
      

6. 泛型的通配符

  • <?>:表示任意類型。

  • <? extends T>:表示 T 或其子類型(上界通配符)。

  • <? super T>:表示 T 或其父類型(下界通配符)。

  • 示例:

    public void printList(List<?> list) {
        for (Object element : list) {
            System.out.println(element);
        }
    }
    

7. 泛型的限制

  • 不能使用基本類型:泛型類型必須是引用類型(如 Integer 而不是 int)。
  • 不能創(chuàng)建泛型數(shù)組:例如 new T[10] 是非法的。
  • 不能實(shí)例化泛型類型:例如 new T() 是非法的。

8. 泛型的應(yīng)用場(chǎng)景

  • 集合框架:如 List<T>、Map<K, V> 等。
  • 工具類:如 Comparator<T>Comparable<T> 等。
  • 自定義數(shù)據(jù)結(jié)構(gòu):如棧、隊(duì)列、鏈表等。

總結(jié)與拓展

  • 泛型的作用:統(tǒng)一集合中元素的類型,提高代碼的安全性和復(fù)用性。
  • 自動(dòng)推斷機(jī)制:JDK 7 引入的鉆石表達(dá)式簡(jiǎn)化了泛型代碼。
  • 自定義泛型:通過(guò)泛型類和泛型方法實(shí)現(xiàn)通用代碼。
  • 通配符<?>、<? extends T>、<? super T> 提供了更靈活的類型約束。
  • 限制:泛型不能使用基本類型、不能創(chuàng)建泛型數(shù)組、不能實(shí)例化泛型類型。

十四、多線程

進(jìn)程是:一個(gè)應(yīng)用程序(1個(gè)進(jìn)程是一個(gè)軟件)

獨(dú)立性:系統(tǒng)分配資源和調(diào)度資源的獨(dú)立單位

動(dòng)態(tài)性:進(jìn)程實(shí)質(zhì)是程序的一次執(zhí)行過(guò)程,進(jìn)程是動(dòng)態(tài)產(chǎn)生,動(dòng)態(tài)消亡的

并發(fā)性:任何進(jìn)程都可以同其他進(jìn)程一起并發(fā)執(zhí)行

線程是:一個(gè)進(jìn)程中的執(zhí)行場(chǎng)景/執(zhí)行單元,是進(jìn)程中單個(gè)順序控制流,是一條執(zhí)行路徑。

并行:同一時(shí)刻,多個(gè)指令在多個(gè)CPU上同時(shí)執(zhí)行

并發(fā):同一時(shí)刻,多個(gè)指令在單個(gè)CPU交替執(zhí)行

線程狀態(tài)轉(zhuǎn)換

1、新建狀態(tài)(New):新創(chuàng)建了一個(gè)線程對(duì)象。

2、就緒狀態(tài)(Runnable):線程對(duì)象創(chuàng)建后,其他線程調(diào)用了該對(duì)象的start()方法。該狀態(tài)的線程位于可運(yùn)行線程池中,變得可運(yùn)行,等待獲取CPU的使用權(quán)。

3、運(yùn)行狀態(tài)(Running):就緒狀態(tài)的線程獲取了CPU,執(zhí)行程序代碼。

4、阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因?yàn)槟撤N原因放棄CPU使用權(quán),暫時(shí)停止運(yùn)行。直到線程進(jìn)入就緒狀態(tài),才有機(jī)會(huì)轉(zhuǎn)到運(yùn)行狀態(tài)。阻塞的情況分三種:

(一)、等待阻塞:運(yùn)行的線程執(zhí)行wait()方法,JVM會(huì)把該線程放入等待池中。(wait會(huì)釋放持有的鎖)

(二)、同步阻塞:運(yùn)行的線程在獲取對(duì)象的同步鎖時(shí),若該同步鎖被別的線程占用,則JVM會(huì)把該線程放入鎖池中。

(三)、其他阻塞:運(yùn)行的線程執(zhí)行sleep()或join()方法,或者發(fā)出了I/O請(qǐng)求時(shí),JVM會(huì)把該線程置為阻塞狀態(tài)

當(dāng)sleep()狀態(tài)超時(shí)、join()等待線程終止或者超時(shí)、或者I/O處理完畢時(shí),線程重新轉(zhuǎn)入就緒狀態(tài)。(注意,sleep是不會(huì)釋放持有的鎖)

5、死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法,該線程結(jié)束生命周期。

線程構(gòu)造方法

構(gòu)造方法名備注
Thread()
Thread(String name)name為線程名字
創(chuàng)建線程第二種方式
Thread(Runnable target)
Thread(Runnable target, String name)name為線程名字

Java 中實(shí)現(xiàn)線程的三種方式總結(jié)

1. 繼承Thread類

  • 實(shí)現(xiàn)方式

    • 編寫一個(gè)類,直接繼承 java.lang.Thread。
    • 重寫 run() 方法,定義線程執(zhí)行的任務(wù)。
  • 創(chuàng)建線程對(duì)象

    MyThread thread = new MyThread();
    
  • 啟動(dòng)線程

    thread.start();
    
  • 特點(diǎn)

    • 簡(jiǎn)單易用,但 Java 是單繼承,繼承 Thread 類后無(wú)法繼承其他類。

2. 實(shí)現(xiàn)Runnable接口

  • 實(shí)現(xiàn)方式

    • 編寫一個(gè)類,實(shí)現(xiàn) java.lang.Runnable 接口。
    • 實(shí)現(xiàn) run() 方法,定義線程執(zhí)行的任務(wù)。
    • 通常使用匿名內(nèi)部類創(chuàng)建。
  • 創(chuàng)建線程對(duì)象

    Runnable task = new MyRunnable();
    Thread thread = new Thread(task);
    
  • 啟動(dòng)線程

    thread.start();
    
  • 特點(diǎn)

    • 更靈活,可以避免單繼承的限制。
    • 適合多個(gè)線程共享同一個(gè)任務(wù)。

3. 使用Callable和Future接口

  • 實(shí)現(xiàn)方式

    • 編寫一個(gè)類,實(shí)現(xiàn) java.util.concurrent.Callable 接口。
    • 實(shí)現(xiàn) call() 方法,定義線程執(zhí)行的任務(wù),并返回結(jié)果。
  • 創(chuàng)建線程對(duì)象

    1. 創(chuàng)建 Callable 實(shí)現(xiàn)類的實(shí)例:

      Callable<Integer> task = new MyCallable();
      
    2. 使用 FutureTask 包裝 Callable 對(duì)象:

      FutureTask<Integer> futureTask = new FutureTask<>(task);
      
    3. 使用 FutureTask 對(duì)象作為 Threadtarget 創(chuàng)建線程:

      Thread thread = new Thread(futureTask);
      
  • 啟動(dòng)線程

    thread.start();
    
  • 獲取結(jié)果

    Integer result = futureTask.get(); // 阻塞直到獲取結(jié)果
    
  • 特點(diǎn)

    • call() 方法可以有返回值和拋出異常。
    • 適合需要獲取線程執(zhí)行結(jié)果的場(chǎng)景。

Future接口的常用方法

  • cancel(boolean mayInterruptIfRunning):嘗試取消任務(wù)。
  • get():獲取任務(wù)結(jié)果,阻塞直到任務(wù)完成。
  • get(long timeout, TimeUnit unit):在指定時(shí)間內(nèi)獲取任務(wù)結(jié)果,超時(shí)拋出 TimeoutException
  • isCancelled():判斷任務(wù)是否被取消。
  • isDone():判斷任務(wù)是否完成。

三種方式的對(duì)比

方式優(yōu)點(diǎn)缺點(diǎn)
繼承 Thread簡(jiǎn)單易用單繼承限制,無(wú)法繼承其他類
實(shí)現(xiàn) Runnable 接口靈活,避免單繼承限制,適合多線程共享任務(wù)無(wú)法直接獲取線程執(zhí)行結(jié)果
使用 CallableFuture可以獲取線程執(zhí)行結(jié)果,支持異常處理,功能更強(qiáng)大使用稍復(fù)雜,需要 FutureTask 包裝

總結(jié)

  • 繼承 Thread:適合簡(jiǎn)單的線程任務(wù),但受限于單繼承。
  • 實(shí)現(xiàn) Runnable 接口:更靈活,適合多線程共享任務(wù)。
  • 使用 CallableFuture:適合需要獲取線程執(zhí)行結(jié)果或處理異常的場(chǎng)景。

根據(jù)具體需求選擇合適的方式實(shí)現(xiàn)多線程編程。

獲取當(dāng)前線程對(duì)象、獲取線程對(duì)象名字、修改線程對(duì)象名字

方法名作用
static Thread currentThread()獲取當(dāng)前線程對(duì)象
String getName()獲取線程對(duì)象名字
void setName(String name)修改線程對(duì)象名字

關(guān)于線程的sleep方法

方法名作用
static void sleep(long millis)讓當(dāng)前線程休眠millis秒

關(guān)于線程中斷sleep()的方法

方法名作用
void interrupt()終止線程的睡眠

Java進(jìn)程的優(yōu)先級(jí)

常量名備注
static int MAX_PRIORITY最高優(yōu)先級(jí)(10)
static int MIN_PRIORITY最低優(yōu)先級(jí)(1)
static int NORM_PRIORITY默認(rèn)優(yōu)先級(jí)(5)

方法:

方法名作用
int getPriority()獲得線程優(yōu)先級(jí)
void setPriority(int newPriority)設(shè)置線程優(yōu)先級(jí)
static void yield()讓位,當(dāng)前線程暫停,回到就緒狀態(tài),讓給其它線程。
void join()將一個(gè)線程合并到當(dāng)前線程中,當(dāng)前線程受阻塞,加入的線程執(zhí)行直到結(jié)束
void join(long millis)接上條,等待該線程終止的時(shí)間最長(zhǎng)為 millis 毫秒
void join(long millis, int nanos)接第一條,等待該線程終止的時(shí)間最長(zhǎng)為 millis 毫秒 + nanos 納秒

多線程并發(fā)環(huán)境下,數(shù)據(jù)的安全問(wèn)題(重點(diǎn))

1.為什么這個(gè)是重點(diǎn)?

以后在開發(fā)中,我們的項(xiàng)目都是運(yùn)行在服務(wù)器當(dāng)中,而服務(wù)器已經(jīng)將線程的定義,線程對(duì)象的創(chuàng)建,線程的啟動(dòng)等,都已經(jīng)實(shí)現(xiàn)完了。這些代碼我們都不需要編寫。

最重要的是: 你要知道,你編寫的程序需要放到一個(gè)多線程的環(huán)境下運(yùn)行,你更需要關(guān)注的是這些數(shù)據(jù)在多線程并發(fā)的環(huán)境下是否是安全的。(重點(diǎn):★★★★★)

2.什么時(shí)候數(shù)據(jù)在多線程并發(fā)的環(huán)境下會(huì)存在安全問(wèn)題呢?★★★★★

滿足三個(gè)條件:

條件1:多線程并發(fā)。

條件2:有共享數(shù)據(jù)。

條件3:共享數(shù)據(jù)有修改的行為。

滿足以上3個(gè)條件之后,就會(huì)存在線程安全問(wèn)題。

3.怎么解決線程安全問(wèn)題呢?

當(dāng)多線程并發(fā)的環(huán)境下,有共享數(shù)據(jù),并且這個(gè)數(shù)據(jù)還會(huì)被修改,此時(shí)就存在線程安全問(wèn)題,怎么解決這個(gè)問(wèn)題?

線程排隊(duì)執(zhí)行。(不能并發(fā))。用排隊(duì)執(zhí)行解決線程安全問(wèn)題。

這種機(jī)制被稱為:線程同步機(jī)制。專業(yè)術(shù)語(yǔ)叫做:線程同步,實(shí)際上就是線程不能并發(fā)了,線程必須排隊(duì)執(zhí)行。

線程同步就是線程排隊(duì)了,線程排隊(duì)了就會(huì) 犧牲一部分效率 ,數(shù)據(jù)安全第一位,只有數(shù)據(jù)安全了,我們才可以談效率。數(shù)據(jù)不安全,沒(méi)有效率的事兒。

死鎖(DeadLock)

死鎖(Deadlock)是多線程編程中的一種常見(jiàn)問(wèn)題,指的是兩個(gè)或多個(gè)線程在執(zhí)行過(guò)程中,因?yàn)闋?zhēng)奪資源而造成的一種互相等待的現(xiàn)象,導(dǎo)致這些線程都無(wú)法繼續(xù)執(zhí)行下去。

死鎖代碼要會(huì)寫。一般面試官要求你會(huì)寫。只有會(huì)寫的,才會(huì)在以后的開發(fā)中注意這個(gè)事兒。因?yàn)樗梨i很難調(diào)試。

死鎖的四個(gè)必要條件

死鎖的發(fā)生必須同時(shí)滿足以下四個(gè)條件:

  1. 互斥條件(Mutual Exclusion)

    • 資源一次只能被一個(gè)線程占用。
  2. 占有并等待(Hold and Wait)

    • 線程已經(jīng)占有了至少一個(gè)資源,但又申請(qǐng)新的資源,而新的資源被其他線程占用。
  3. 不可搶占(No Preemption)

    • 線程已占有的資源不能被其他線程強(qiáng)行搶占,必須由線程自己釋放。
  4. 循環(huán)等待(Circular Wait)

    • 存在一個(gè)線程的等待循環(huán)鏈,每個(gè)線程都在等待下一個(gè)線程所占用的資源。

Java 中的死鎖示例

以下是一個(gè)經(jīng)典的死鎖代碼示例,展示了兩個(gè)線程互相等待對(duì)方釋放鎖的情況:

public class DeadlockExample {
    private static final Object lock1 = new Object();
    private static final Object lock2 = new Object();

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            synchronized (lock1) {
                System.out.println("Thread 1: Holding lock 1...");
                try {
                    Thread.sleep(100); // 模擬操作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread 1: Waiting for lock 2...");
                synchronized (lock2) {
                    System.out.println("Thread 1: Acquired lock 2!");
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (lock2) {
                System.out.println("Thread 2: Holding lock 2...");
                try {
                    Thread.sleep(100); // 模擬操作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread 2: Waiting for lock 1...");
                synchronized (lock1) {
                    System.out.println("Thread 2: Acquired lock 1!");
                }
            }
        });

        thread1.start();
        thread2.start();
    }
}
代碼分析
  1. 線程1

    • 先獲取lock1,然后嘗試獲取lock2。
    • 在獲取lock2之前,線程1會(huì)休眠100毫秒。
  2. 線程2

    • 先獲取lock2,然后嘗試獲取lock1
    • 在獲取lock1之前,線程2會(huì)休眠100毫秒。
  3. 死鎖發(fā)生

    • 線程1持有lock1并等待lock2。
    • 線程2持有lock2并等待lock1。
    • 兩個(gè)線程互相等待,導(dǎo)致死鎖。

如何避免死鎖

  1. 避免嵌套鎖

    • 盡量不要在持有一個(gè)鎖的同時(shí)去申請(qǐng)另一個(gè)鎖。
  2. 按順序獲取鎖

    • 如果多個(gè)線程需要獲取多個(gè)鎖,確保它們以相同的順序獲取鎖。
  3. 使用超時(shí)機(jī)制

    • 在獲取鎖時(shí)設(shè)置超時(shí)時(shí)間,如果超時(shí)則釋放已持有的鎖并重試。
  4. 使用工具檢測(cè)

    • 使用工具(如jstack)檢測(cè)死鎖。

死鎖的調(diào)試與檢測(cè)

  1. 使用jstack

    • 運(yùn)行程序后,使用jstack命令查看線程狀態(tài),可以檢測(cè)到死鎖。
  2. 日志輸出

    • 在代碼中添加日志,記錄鎖的獲取和釋放情況。
  3. 使用工具

    • 使用IDE(如IntelliJ IDEA)或第三方工具(如VisualVM)檢測(cè)死鎖。

守護(hù)線程

在Java中,線程分為兩大類:用戶線程守護(hù)線程。守護(hù)線程(Daemon Thread)是一種特殊的線程,它的生命周期依賴于用戶線程。當(dāng)所有的用戶線程結(jié)束時(shí),守護(hù)線程會(huì)自動(dòng)退出。

守護(hù)線程的特點(diǎn)

  1. 依賴用戶線程

    • 守護(hù)線程是為用戶線程提供服務(wù)的線程。
    • 當(dāng)所有的用戶線程結(jié)束時(shí),守護(hù)線程會(huì)自動(dòng)退出。
  2. 典型代表

    • 垃圾回收線程(GC)是Java中最典型的守護(hù)線程。
  3. 主線程是用戶線程

    • main方法所在的線程是用戶線程。
  4. 死循環(huán)

    • 守護(hù)線程通常是一個(gè)死循環(huán),持續(xù)執(zhí)行某些后臺(tái)任務(wù)。

守護(hù)線程的應(yīng)用場(chǎng)景

  1. 定時(shí)任務(wù)

    • 例如,每天00:00自動(dòng)備份系統(tǒng)數(shù)據(jù)。
    • 可以使用定時(shí)器(如TimerScheduledExecutorService),并將定時(shí)任務(wù)設(shè)置為守護(hù)線程。
  2. 后臺(tái)監(jiān)控

    • 例如,監(jiān)控系統(tǒng)資源使用情況、日志清理等。
  3. 垃圾回收

    • Java的垃圾回收線程就是一個(gè)守護(hù)線程。

守護(hù)線程的設(shè)置

在Java中,可以通過(guò)setDaemon(boolean on)方法將一個(gè)線程設(shè)置為守護(hù)線程:

方法簽名說(shuō)明
void setDaemon(boolean on)ontrue表示將線程設(shè)置為守護(hù)線程

注意

  • 必須在調(diào)用start()方法之前設(shè)置守護(hù)線程,否則會(huì)拋出IllegalThreadStateException。
  • 守護(hù)線程中創(chuàng)建的子線程默認(rèn)也是守護(hù)線程。

代碼示例

以下是一個(gè)守護(hù)線程的示例,展示了如何設(shè)置守護(hù)線程以及它的行為:

public class DaemonThreadExample {
    public static void main(String[] args) {
        Thread daemonThread = new Thread(() -> {
            while (true) {
                System.out.println("守護(hù)線程正在運(yùn)行...");
                try {
                    Thread.sleep(1000); // 模擬任務(wù)執(zhí)行
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // 設(shè)置為守護(hù)線程
        daemonThread.setDaemon(true);

        // 啟動(dòng)守護(hù)線程
        daemonThread.start();

        // 主線程(用戶線程)執(zhí)行任務(wù)
        System.out.println("主線程開始執(zhí)行...");
        try {
            Thread.sleep(5000); // 模擬主線程執(zhí)行任務(wù)
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("主線程執(zhí)行完畢,程序退出。");
    }
}
代碼分析
  1. 守護(hù)線程

    • 守護(hù)線程是一個(gè)死循環(huán),每隔1秒輸出一條消息。
    • 設(shè)置為守護(hù)線程后,當(dāng)主線程結(jié)束時(shí),守護(hù)線程會(huì)自動(dòng)退出。
  2. 主線程

    • 主線程執(zhí)行5秒后結(jié)束。
    • 主線程結(jié)束后,守護(hù)線程也會(huì)自動(dòng)退出。

守護(hù)線程的注意事項(xiàng)

  1. 資源釋放

    • 守護(hù)線程中不要執(zhí)行關(guān)鍵任務(wù)(如文件寫入、數(shù)據(jù)庫(kù)操作等),因?yàn)樗耐顺鍪遣豢煽氐摹?/li>
  2. 線程優(yōu)先級(jí)

    • 守護(hù)線程的優(yōu)先級(jí)通常較低,適合執(zhí)行后臺(tái)任務(wù)。
  3. 生命周期

    • 守護(hù)線程的生命周期依賴于用戶線程,不能獨(dú)立存在。

定時(shí)器的作用:

間隔特定的時(shí)間,執(zhí)行特定的程序。在實(shí)際的開發(fā)中,每隔多久執(zhí)行一段特定的程序,這種需求是很常見(jiàn)的,那么在java中其實(shí)可以采用多種方式實(shí)現(xiàn):

可以使用sleep方法,睡眠,設(shè)置睡眠時(shí)間,沒(méi)到這個(gè)時(shí)間點(diǎn)醒來(lái),執(zhí)行任務(wù)。這種方式是最原始的定時(shí)器。(比較low)

在java的類庫(kù)中已經(jīng)寫好了一個(gè)定時(shí)器:java.util.Timer,可以直接拿來(lái)用。

不過(guò),這種方式在目前的開發(fā)中也很少用,因?yàn)楝F(xiàn)在有很多高級(jí)框架都是支持定時(shí)任務(wù)的。

在實(shí)際的開發(fā)中,目前使用較多的是Spring框架中提供的SpringTask框架,這個(gè)框架只要進(jìn)行簡(jiǎn)單的配置,就可以完成定時(shí)器的任務(wù)。

構(gòu)造方法名備注
Timer()創(chuàng)建一個(gè)定時(shí)器
Timer(boolean isDaemon)isDaemon為true為守護(hù)線程定時(shí)器
Timer(String name)創(chuàng)建一個(gè)定時(shí)器,其線程名字為name
Timer(String name, boolean isDaemon)結(jié)合2、3
方法名作用
void schedule(TimerTask task, Date firstTime, long period)安排指定的任務(wù)在指定的時(shí)間開始進(jìn)行重復(fù)的固定延遲執(zhí)行
void cancel()終止定時(shí)器

關(guān)于Object類的wait()、notify()、notifyAll()方法

方法名作用
void wait()讓活動(dòng)在當(dāng)前對(duì)象的線程無(wú)限等待(釋放之前占有的鎖)
void notify()喚醒當(dāng)前對(duì)象正在等待的線程(只提示喚醒,不會(huì)釋放鎖)
void notifyAll()喚醒當(dāng)前對(duì)象全部正在等待的線程(只提示喚醒,不會(huì)釋放鎖)

wait和notify方法不是線程對(duì)象的方法,是java中任何一個(gè)java對(duì)象都有的方法,因?yàn)檫@兩個(gè)方法是 Object類中自帶 的。

wait方法和notify方法不是通過(guò)線程對(duì)象調(diào)用

調(diào)用:

Object o = new Object();

o.wait();

總結(jié) ★★★★★(呼應(yīng)生產(chǎn)者消費(fèi)者模式)

1、wait和notify方法不是線程對(duì)象的方法,是普通java對(duì)象都有的方法。

2、wait方法和notify方法建立在 線程同步 的基礎(chǔ)之上。因?yàn)槎嗑€程要同時(shí)操作一個(gè)倉(cāng)庫(kù)。有線程安全問(wèn)題。

3、wait方法作用:o.wait() 讓正在o對(duì)象上活動(dòng)的線程t進(jìn)入等待狀態(tài),并且釋放掉t線程之前占有的o對(duì)象的鎖

4、notify方法作用:o.notify() 讓正在o對(duì)象上等待的線程喚醒,只是通知,不會(huì)釋放o對(duì)象上之前占有的鎖。

生產(chǎn)者消費(fèi)者模式(wait()和notify())

什么是“生產(chǎn)者和消費(fèi)者模式”?

生產(chǎn)線程負(fù)責(zé)生產(chǎn),消費(fèi)線程負(fù)責(zé)消費(fèi)。

生產(chǎn)線程和消費(fèi)線程要達(dá)到均衡。

這是一種特殊的業(yè)務(wù)需求,在這種特殊的情況下需要使用wait方法和notify方法。

模擬一個(gè)業(yè)務(wù)需求

倉(cāng)庫(kù)我們采用List集合。

List集合中假設(shè)只能存儲(chǔ)1個(gè)元素。

1個(gè)元素就表示倉(cāng)庫(kù)滿了。

如果List集合中元素個(gè)數(shù)是0,就表示倉(cāng)庫(kù)空了。

保證List集合中永遠(yuǎn)都是最多存儲(chǔ)1個(gè)元素。

必須做到這種效果:生產(chǎn)1個(gè)消費(fèi)1個(gè)。

十五、反射

1. Class 對(duì)象概述

  • Class 對(duì)象:在 Java 中,每個(gè)類在加載到內(nèi)存時(shí)都會(huì)生成一個(gè) Class 對(duì)象,該對(duì)象存儲(chǔ)了類的所有信息(如方法、構(gòu)造函數(shù)、字段等)。
  • 反射:通過(guò) Class 對(duì)象,可以在運(yùn)行時(shí)動(dòng)態(tài)獲取類的信息并操作類的成員(如調(diào)用方法、訪問(wèn)字段等)。

2. Class 對(duì)象的生成方式

  1. 類名.class

    • JVM 將類加載到內(nèi)存中,但不進(jìn)行初始化。

    • 返回該類的 Class 對(duì)象。

    • 示例:

      Class<?> clazz = String.class;
      
  2. Class.forName("包名.類名")

    • 加載類并默認(rèn)進(jìn)行靜態(tài)初始化。

    • 返回該類的 Class 對(duì)象。

    • 示例:

      Class<?> clazz = Class.forName("java.lang.String");
      
  3. Class.forName("包名.類名", false, 類加載器)

    • 第二個(gè)參數(shù)為 false 時(shí),不進(jìn)行初始化;為 true 時(shí),進(jìn)行初始化。

    • 示例:

      Class<?> clazz = Class.forName("java.lang.String", false, ClassLoader.getSystemClassLoader());
      
  4. 實(shí)例對(duì)象.getClass()

    • 對(duì)類進(jìn)行靜態(tài)初始化和非靜態(tài)初始化。

    • 返回運(yùn)行時(shí)實(shí)際對(duì)象所屬類的 Class 對(duì)象。

    • 示例:

      String str = "Hello";
      Class<?> clazz = str.getClass();
      

3. Class 對(duì)象的特性

  • 父子類 Class 對(duì)象不一致
    • 如果 AB 的子類,則 A.classB.class 返回的 Class 對(duì)象不同。
    • 如果 aA 的實(shí)例,則 A.classa.getClass() 返回的 Class 對(duì)象一致。

4. Class 類的常用方法

  • getName():返回類的全限定名(包名 + 類名)。
  • getSuperclass():返回類的直接父類的 Class 對(duì)象。
  • getInterfaces():返回類實(shí)現(xiàn)的所有接口的 Class 數(shù)組。
  • isArray():判斷該類是否是數(shù)組類型。
  • isEnum():判斷該類是否是枚舉類型。
  • isInterface():判斷該類是否是接口。
  • isPrimitive():判斷該類是否是基本類型(如 intboolean 等)。
  • isAssignableFrom(Class cls):判斷該類是否是 cls 的父類或父接口。
  • getComponentType():如果該類是數(shù)組類型,返回?cái)?shù)組的組件類型。
  • asSubclass(Class clazz):將當(dāng)前 Class 對(duì)象轉(zhuǎn)換為 clazz 的子類類型。

5.asSubclass方法的使用

  • 作用:將當(dāng)前 Class 對(duì)象轉(zhuǎn)換為指定類的子類類型。

  • 示例

    List<String> strList = new ArrayList<>();
    Class<? extends List> strListCast = strList.getClass().asSubclass(List.class);
    
  • 動(dòng)態(tài)加載時(shí)的應(yīng)用

    Class.forName("xxx.xxx.xxx").asSubclass(List.class).newInstance();
    
    • 如果 xxx.xxx.xxxList 的子類,則正常執(zhí)行;否則拋出 ClassCastException。

6. 靜態(tài)加載與動(dòng)態(tài)加載

  • 靜態(tài)加載:通過(guò) new ClassName() 加載類,編譯時(shí)必須提供類的定義。
  • 動(dòng)態(tài)加載:通過(guò) Class.forName("ClassName") 加載類,編譯時(shí)可以缺席,運(yùn)行時(shí)按需提供。

總結(jié)

  • Class 對(duì)象:存儲(chǔ)類的所有信息,是反射機(jī)制的核心。
  • 生成方式類名.class、Class.forName()實(shí)例對(duì)象.getClass()。
  • 常用方法getName()、getSuperclass()、getInterfaces()、asSubclass() 等。
  • asSubclass:用于將 Class 對(duì)象轉(zhuǎn)換為指定類的子類類型。
  • 靜態(tài)加載與動(dòng)態(tài)加載:靜態(tài)加載在編譯時(shí)提供類定義,動(dòng)態(tài)加載在運(yùn)行時(shí)按需提供。

通過(guò)掌握 Class 對(duì)象和反射機(jī)制,可以在運(yùn)行時(shí)動(dòng)態(tài)操作類的成員,實(shí)現(xiàn)靈活的編程。

十六、小游戲(進(jìn)擊的小鳥)

public class StartGame {           //游戲開始類
  public static void main(String[] args) throws InterruptedException {
    JFrame jFrame = new JFrame("進(jìn)擊の小鳥");  //創(chuàng)建窗口對(duì)象
    jFrame.setSize(400,600);//窗口大小
    jFrame.setLocationRelativeTo(null); //窗口相對(duì)位置
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設(shè)定點(diǎn)擊關(guān)閉結(jié)束程序

?    BirdGame birdGame = new BirdGame();  //初始化游戲?qū)ο箢?
?    jFrame.add(birdGame);         //把創(chuàng)建好的對(duì)象加進(jìn)來(lái)
?    jFrame.setVisible(true);       //讓窗口可視化
?    birdGame.action();          //地面運(yùn)動(dòng)方法

  }
}
public class Bird {
  public BufferedImage images[];
  public BufferedImage image;   //存放小鳥圖片
  public int x;
  public int y;
  public int width;
  public int height;
  public int index=0;
  public double speed=0;    //小鳥初始速度
  public double upspeed=30;  //初始上拋速度
  public double s=0;      //經(jīng)過(guò)t,發(fā)生的位移
  public double t=0.2;     //發(fā)生位移時(shí)間
  public double g=9.8;     //重力加速度
  public Bird() throws IOException {
    x=120;
    y=120;
    images=new BufferedImage[8];
    image= ImageIO.read(getClass().getResource("0.png"));
    width=image.getWidth();
    height=image.getHeight();
    for (int i=0;i<images.length;i++) {
      images[i] = ImageIO.read(getClass().getResource(i+".png"));
    }
  }


  public void fly(){      //小鳥飛飛
    index++;
    image=images[index/2%8];
  }
  public void upSpeed(){    //鼠標(biāo)點(diǎn)擊游戲屏幕,給小鳥一個(gè)初始上拋速度
    speed=upspeed;
  }
  public void distanceChange(){  //實(shí)現(xiàn)小鳥速度,位移,縱坐標(biāo)變化
    double v=speed; //初始速度
    s=v*t-g*t*t/2;  //經(jīng)過(guò)t小鳥的位移
    speed=v-g*t;   //小鳥經(jīng)過(guò)時(shí)間t的末速度
    y=y-(int)s;      //經(jīng)過(guò)時(shí)間t后,小鳥的y

  }
}
public class Column {    //管道類
  public BufferedImage cImage;
  public int x;
  public  int y;
  public int width;
  public int height;
  public  int distance=270;  //兩根管道之間的距離
  public static  int count=0;
  Random random = new Random();
  public Column() throws IOException {
    cImage= ImageIO.read(getClass().getResource("column.png"));
    x=450+distance*count;
    width=cImage.getWidth();   //獲得管道的寬
    height=cImage.getHeight();  //高
    y=-( height/2-random.nextInt(300)-50);


    count++;
  }
  public void step(){
    x-=5; //讓地面往左運(yùn)動(dòng)
    if (x<=-width/2){
      x=x+distance*2;
      y=-(height/2-random.nextInt(300)-50) ;
      //x=400;
    }
  }
}
public class Ground {  //地面類
  public BufferedImage image; //存放地面圖片
  public int x;
  public int y;

  public Ground() {

?    try {
?      x=0;
?      y=500;
?      image= ImageIO.read(getClass().getResource("ground.png"));
?    } catch (IOException e) {
?      e.printStackTrace();
?    }
  }
  public void step(){
?    x-=1; //讓地面往左運(yùn)動(dòng)
?    if (x==-100){
?      x=0;
?    }
  }
}
public class Music implements Runnable {    //音樂(lè)類
  Player player=null;
  @Override
  public void run() {
    InputStream resourceAsStream = this.getClass().getResourceAsStream("2.mp3");
    try {
      player=new Player(resourceAsStream);
      player.play();
    } catch (JavaLayerException e) {
      e.printStackTrace();
    }

  }
  public void stopBGM(){
  if (player!=null)
      player.close();

  }
}
public class Score {  //連接對(duì)象
  private String sid;
  private int score;
  private String time;

  public String getSid() {
    return sid;
  }

  public void setSid(String sid) {
    this.sid = sid;
  }

  public int getScore() {
    return score;
  }

  public void setScore(int score) {
    this.score = score;
  }

  public String getTime() {
    return time;
  }

  public void setTime(String time) {
    this.time = time;
  }
}
public class ScoreManager {   //jdbc連接
  static{
    try {
      Class.forName("com.mysql.cj.jdbc.Driver");
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }
  public List<Score> selectAllScore(){     //查詢方法
    List<Score> list = new ArrayList<>();

?    try {
?      String sql="select * from score order by time";
?      Connection conn = DriverManager.getConnection("jdbc:mysql://cdb-kthncrwi.bj.tencentcdb.com:10159/flybird?useUnicode=true", "student", "521qianfeng");
?      PreparedStatement pst = conn.prepareStatement(sql);
?      ResultSet resultSet = pst.executeQuery();
?      while (resultSet.next()){
?        Score score = new Score();
?        score.setSid(resultSet.getString("sid"));
?        score.setScore(resultSet.getInt("score"));
?        score.setTime(resultSet.getString("time"));
?        list.add(score);
?      }
?    } catch (SQLException e) {
?      e.printStackTrace();
?    }

?    return list;
  }
  public int insertScore(int score) {     //插入方法
?    int num = 0;
?    String sql = "insert into score(sid,score,time) value(?,?,?)";
?    try {
?      Connection conn = DriverManager.getConnection("jdbc:mysql://cdb-kthncrwi.bj.tencentcdb.com:10159/flybird?useUnicode=true", "student", "521qianfeng");
?      PreparedStatement pst = conn.prepareStatement(sql);
?      String sid= UUID.randomUUID().toString();     //隨機(jī)生成id
?      pst.setString(1,sid);
?      pst.setInt(2,score);
?      Date date = new Date();
?      SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");     //創(chuàng)建時(shí)間類型對(duì)象
?      String time=simpleDateFormat.format(date);
?      pst.setString(3,time);
?      num=pst.executeUpdate();
?    } catch (SQLException e) {
?      e.printStackTrace();
?    }
?    return num;

  }
}
public class BirdGame extends JPanel {   //自定義面板類繼承面板類
  ScoreManager sc=new ScoreManager();
  public JPanel jp=new JPanel();
  public BufferedImage bg;         //圖片緩沖區(qū)(在顯示圖片前對(duì)圖片進(jìn)行操作 eg:.getWidth()寬,.getHeight()高)
  public BufferedImage startbg;
  public BufferedImage overbg;
  public Ground ground;
  public Bird bird;
  public Column columns[];
  public Music music;

  String file="H:\\Java程序\\小程序\\src\\小鳥\\png\\bg.png";

  public int state; //表示游戲狀態(tài)
  public static final int START=0;   //開始
  public static final int RUNNING=1;  //運(yùn)行
  public static final int GAMEOVER=2; //結(jié)束
  public static int score=0;      //初始積分

  public BirdGame(){
    try {
      state=START;         //游戲初始為游戲開始狀態(tài)
      ground=new Ground();     //創(chuàng)建地面類對(duì)象,調(diào)用地面類構(gòu)造方法
      bird = new Bird();
      columns=new Column[2];
      music = new Music();
      for (int i=0;i<columns.length;i++){
        columns[i]=new Column();
      }
      bg= ImageIO.read(getClass().getResource("bg.png")); //讀取這張圖片并把圖片值賦給變量
      //bg=ImageIO.read(new File(file));
      //bg=ImageIO.read(new File("src/小鳥/png/bg.png"));
      startbg=ImageIO.read(getClass().getResource("start.png"));
      overbg=ImageIO.read(getClass().getResource("gameover.png"));
    } catch (IOException e) {
      e.printStackTrace();
    }
   }



  @Override
  public void paint(Graphics g) {         //繪制一次的畫畫方法
    super.paint(g);               //調(diào)用畫筆
    g.drawImage(bg,0,0,null);            //繪制背景(最后一個(gè)參數(shù)為觀察者
    switch (state){
      case START:
        //繪制游戲開始圖片
        settishi(g);
        g.drawImage(startbg,0,0,null);

?        break;
?      case RUNNING:
?        for (int i=0;i<columns.length;i++) {
?          g.drawImage(columns[i].cImage, columns[i].x, columns[i].y, null);
?        }
?        break;
?      case GAMEOVER:
?        //繪制游戲結(jié)束圖片
?        settishi2(g);
?        g.drawImage(overbg,0,0,null);

?        break;

?    }
?    g.drawImage(ground.image,ground.x,ground.y,null);  //繪制地面
?    g.drawImage(bird.image,bird.x, bird.y,null);     //繪制小鳥

?    setScore(g);
  }
  public boolean isHitGround(){      //撞擊地面
?    if (bird.y+bird.height>500){
?      return true;
?    }else {
?      return false;
?    }
  }
  public boolean isHitSky(){      //撞擊天空
?    if (bird.y<0){
?      return true;
?    }else {
?      return false;
?    }
  }
  public boolean isguandao(Column c) {
?    if (bird.x + bird.width >= c.x && c.x + c.width >= bird.x) {   //撞擊管道左右
?      if (bird.y <= c.height / 2 + c.y - 72 || bird.y + bird.height >= c.height / 2 + c.y + 72) {
?        return true;
?      } else {
?        return false;
?      }

?    } else {
?      return false;
?    }
  }

  public void setScore(Graphics g){               //繪制分?jǐn)?shù)方法
    Font font = new Font(Font.SERIF, Font.ITALIC, 40);  //羅馬字體,斜體,40號(hào)
    g.setFont(font);     //獲取字體
    g.setColor(Color.white);//獲取顏色
    g.drawString(score+"分",40,60);    //畫字符串
  }
  public void settishi(Graphics g){               //繪制分?jǐn)?shù)方法
    Font font1 = new Font(Font.SERIF, Font.BOLD, 25);  //羅馬字體,斜體,40號(hào)
    g.setFont(font1);     //獲取字體
    g.setColor(Color.black);//獲取顏色
    g.drawString("點(diǎn)擊屏幕開始運(yùn)行",110,400);    //畫字符串
    g.drawString("   制作人---趙嘉盟",120,430);
  }
  public void settishi2(Graphics g){               //繪制分?jǐn)?shù)方法
    Font font2 = new Font(Font.SANS_SERIF, Font.BOLD, 30);  //羅馬字體,斜體,40號(hào)
    g.setFont(font2);     //獲取字體
    g.setColor(Color.red);//獲取顏色
    g.drawString("點(diǎn)擊屏幕重新開始",100,500);    //畫字符串
  }
  public void action() throws InterruptedException {    //游戲?qū)ο筮\(yùn)動(dòng)方法
    this.addMouseListener(new BirdMouseListener());   //添加鼠標(biāo)監(jiān)聽器

?    while (true){
?      switch (state){     //狀態(tài)不同,對(duì)象運(yùn)動(dòng)效果不同
?        case START:
?          ground.step();  //調(diào)用地面運(yùn)動(dòng)方法
?          bird.fly();


          break;
        case RUNNING:

?          bird.distanceChange();
?          ground.step();  //調(diào)用地面運(yùn)動(dòng)方法
?          bird.fly();

?          if (isHitGround()||isHitSky()){
?            state=GAMEOVER;
?            break;
?          }
?          for (int i=0;i<columns.length;i++){
?            Column cl=columns[i];
?            cl.step();
?            if (isguandao(cl)){
?              state=GAMEOVER;
?              break;
?            }
?            if (bird.x==cl.x){
?              score++;
?            }
?          }

?          break;
?        case GAMEOVER:
?          music.stopBGM();
?          break;
?      }
?      repaint();  //刷新方法(重新繪制)
?      Thread.sleep(50);  //線程睡眠
?    }
  }
  class BirdMouseListener extends MouseAdapter{      //小鳥飛行鼠標(biāo)控制監(jiān)聽內(nèi)部類
?    @Override
?    public void mousePressed(MouseEvent e) {
?      super.mousePressed(e);

?      switch (state){
?        case START:
?          state=RUNNING;  //鼠標(biāo)點(diǎn)擊開始運(yùn)行
?          Thread thread = new Thread(music);
?          thread.start();
?          break;
?        case RUNNING:
?          bird.upSpeed(); //鼠標(biāo)點(diǎn)擊屏幕給小鳥一個(gè)初始上拋速度
?          break;
?        case GAMEOVER:
?          sc.insertScore(score);  //向數(shù)據(jù)庫(kù)插入分?jǐn)?shù)
?          List<Score> scores = sc.selectAllScore();//查詢數(shù)據(jù)庫(kù)所有分?jǐn)?shù)
?          String message="";
?          for (Score score1 : scores) {
?            message=message+"時(shí)間:"+score1.getTime()+"\n分?jǐn)?shù):"+score1.getScore()+"\n";
?          }
?          JOptionPane.showConfirmDialog(jp,message,"實(shí)時(shí)分?jǐn)?shù)",JOptionPane.WARNING_MESSAGE);
?          state=START;   //鼠標(biāo)點(diǎn)擊游戲恢復(fù)開始狀態(tài)

?          bird.x=120;
?          bird.y=220;
?          bird.speed=0;
?          Column.count=0;
?          try {
?            columns[0] = new Column();
?          } catch (IOException ex) {
?            ex.printStackTrace();
?          }
?          try {
?            columns[1] = new Column();
?          } catch (IOException ex) {
?            ex.printStackTrace();
?          }
?          score = 0;//給積分初始化
?          for (int i=0;i<columns.length;i++){
?            try {
?              columns[i]=new Column();
?            } catch (IOException ex) {
?              ex.printStackTrace();
?            }
?          }

?          break;

?      }
?    }
  }
}

十七、Stream

Stream簡(jiǎn)介

Java 8 中的 Stream 是對(duì)(Collection)集合對(duì)象功能的增強(qiáng),它專注于對(duì)集合對(duì)象進(jìn)行各種非常便利、高效的聚合操作

或大批量數(shù)據(jù)操作。Stream API 借助于同樣新出現(xiàn)的 Lambda 表達(dá)式,極大的提高編程效率和程序可讀性。

Stream原理

這種編程風(fēng)格將要處理的元素集合看作一種流,流在管道中傳輸,并且可以在管道的節(jié)點(diǎn)上進(jìn)行處理,比如篩選,排序,聚合等。

元素流在管道中經(jīng)過(guò)中間操作(intermediate operation)的處理,最后由最終操作(terminal operation)得到前面處理的

結(jié)果。

Stream優(yōu)點(diǎn)

(1)速度更快

(2)代碼更少(增加了新的語(yǔ)法Lambda表達(dá)式)

(3)強(qiáng)大的Stream API

(4)便于并行

(5)最大化減少了空指針異常Optional

Stream的操作三個(gè)步驟:

(1)創(chuàng)建Stream,一個(gè)數(shù)據(jù)源(如:集合、數(shù)組),獲取一個(gè)流;

(2)中間操作,一個(gè)中間操作鏈,對(duì)數(shù)據(jù)源的數(shù)據(jù)進(jìn)行處理;

(3)終止操作,一個(gè)終止操作,執(zhí)行中間操作鏈,并產(chǎn)生結(jié)果。

集合有兩種方式生成流:

stream() − 為集合創(chuàng)建串行流。

parallelStream() − 為集合創(chuàng)建并行流

-Stream的的中間操作(intermediate)和最終操作(terminal)都包含的方法:

中間操作(intermediate)

1.filter : 通過(guò)設(shè)置條件來(lái)過(guò)濾元素。

List<String> list = Arrays.asList("aaa","ddd","bbb","ccc","a2a","d2d","b2b","c2c","a3a","d3d","b3b","c3c");

list.stream().filter((s)->s.contains("a")).forEach(s -> System.out.println(s));

以上代碼使用filter方法過(guò)濾出只包含”a”的元素,然后通過(guò)forEach將滿足條件的元素遍歷出來(lái)。

map : 就是將對(duì)應(yīng)的元素使用給定方法進(jìn)行轉(zhuǎn)換。

List<String> list = Arrays.asList("aaa","ddd","bbb","ccc","a2a","d2d","b2b","c2c","a3a","d3d","b3b","c3c");

list.stream().filter((s)->s.contains("a")).map((s)-> s + "---map").forEach(s -> System.out.println(s));

在filter的基礎(chǔ)上,給每個(gè)元素后面添加字符串”—map”

flatMap:如果流的元素為數(shù)組或者Collection,flatMap就是將每個(gè)Object[]元素或Collection元素都轉(zhuǎn)換為Object元素。

List<String[]> setList = new ArrayList<>();

setList.add(new String[]{"aa","bb"});

setList.add(new String[]{"cc","dd"});

setList.add(new String[]{"ee","ff"});//使用map方法

setList.stream().map(s->Arrays.stream(s)).forEach(s-> System.out.println("map==" + s));//使用flatMap方法

setList.stream().flatMap(s->Arrays.stream(s)).forEach(s-> System.out.println("flatMap==" + s));

map就是將數(shù)組流直接返回,flatMap是將數(shù)組流中的每個(gè)元素都返回。

.distinct:將集合中的元素去重。

List<String> disList = Arrays.asList("aaa","ddd","bbb","ddd","aaa");

disList.stream().distinct().forEach(s-> System.out.println(s));

sorted:將集合中的元素排序。

List<Integer> integerList = Arrays.asList(2,4,1,3);

integerList.stream().sorted().forEach(s-> System.out.println(s));

可以按照自定義排序:

List<Integer> integerList = Arrays.asList(2,4,1,3);

integerList.stream().sorted((s1,s2)->s2.compareTo(s1)).forEach(s-> System.out.println(s));

peek:生成一個(gè)包含原Stream的所有元素的新Stream,同時(shí)會(huì)提供一個(gè)消費(fèi)函數(shù)即引用的方法A,當(dāng)Stream每個(gè)元素被消費(fèi)的時(shí)候都會(huì)先
執(zhí)行新Stream給定的方法A。peek是中間操作,如果peek后沒(méi)有最終操作,則peek不會(huì)執(zhí)行。

List<Integer> integerList = Arrays.asList(1,2,3,4);

integerList.stream().peek(s-> System.out.println("peek = "+s)).forEach(s-> System.out.println("forEach = "+s));

limit:返回Stream的前n個(gè)元素。

List<Integer> integerList = Arrays.asList(1,2,3,4);

integerList.stream().limit(2).forEach(s-> System.out.println(s));

skip:刪除Stream的前n個(gè)元素。

List<Integer> integerList = Arrays.asList(1,2,3,4);

integerList.stream().skip(2).forEach(s-> System.out.println(s));

終端操作(terminal)

1.forEach:遍歷Stream中的每個(gè)元素,前面每個(gè)例子都有使用,此處不再演示。

List<Integer> integerList = Arrays.asList(1,2,3,4);

integerList.stream().skip(2).forEach(s-> System.out.println(s));

forEachOrdered:遍歷Stream中的每個(gè)元素。
區(qū)別: 在串行流(stream)中沒(méi)有區(qū)別,在并行流(parallelStream)中如果數(shù)據(jù)源是有序集合,forEachOrdered輸出順序與數(shù)據(jù)源中順序
一致,forEach則是亂序。

List<Integer> integerList = Arrays.asList(1,2,3,4);

integerList.parallelStream().forEachOrdered(s-> System.out.println(s));

toArray:將流轉(zhuǎn)換為Object[]或者指定類型的數(shù)組。

List<Integer> integerList = Arrays.asList(1,2,3,4);

Object[] array = integerList.stream().toArray();

String[] strArr = integerList.stream().toArray(String[]::new);

Stream中的toArray普通情況下和集合中的toArray沒(méi)什么區(qū)別,但是Stream中的toArray轉(zhuǎn)換為指定類型的數(shù)組。

reduce:將集合中的每個(gè)元素聚合成一條數(shù)據(jù)。有三種情況:

reduce(BinaryOperator accumulator):此處需要一個(gè)參數(shù),返回Optional對(duì)象:

Optional reduce = integerList.stream().reduce((a, b) -> a + b);

reduce(T identity, BinaryOperator accumulator):此處需要兩個(gè)參數(shù),第一個(gè)參數(shù)為起始值,第二個(gè)參數(shù)為引用的方法

從起始值開始,每個(gè)元素執(zhí)行一次引用的方法(方法引用的中的兩個(gè)參數(shù):第一個(gè)參數(shù)為上個(gè)元素執(zhí)行方法引用的結(jié)果,第二個(gè)參數(shù)為當(dāng)前元素)。

  List<Integer> integerList = Arrays.asList(1,2,3,4);

  int integer = integerList.stream().reduce(5,(a, b) -> a + b);

  System.out.println(integer);

此例中使用起始值為5,對(duì)集合中每個(gè)元素求和,可以理解為:5+1+2+3+4=15。

**reduce:**此處需要三個(gè)參數(shù)。此方法用在并發(fā)流(parallelStream)中,啟動(dòng)多個(gè)子線程使用accumulator進(jìn)行并行計(jì)算,最終使用combiner對(duì)子線程結(jié)果進(jìn)行合并,返回identity類型的數(shù)據(jù)。

collect:將流轉(zhuǎn)換成集合或聚合元素。有兩種情況。接受一個(gè)參數(shù)和接受三個(gè)參數(shù)(三個(gè)參數(shù)在并發(fā)流parallelStream中使用),此處介紹一個(gè)參數(shù)的情況,單個(gè)參數(shù)接受的參數(shù)類型為Collector,Collectors 類實(shí)現(xiàn)了很多歸約操作

List<Integer> integerList = Arrays.asList(2,4,1,3);List<Integer> integers = integerList.stream().filter(s -> s > 1).collect(Collectors.toList());System.out.println(integers.toString());

此處統(tǒng)計(jì)集合中大于1的元素并最終返回list。

min:獲取集合中最小值。

List<Integer> integerList = Arrays.asList(2,4,1,3);Integer min = integerList.stream().min(Integer::compareTo).get();System.out.println(min);

max:獲取集合中最大值。

List<Integer> integerList = Arrays.asList(2,4,1,3);Integer max = integerList.stream().max(Integer::compareTo).get();System.out.println(max);

count:獲取集合中元素個(gè)數(shù)

List<Integer> integerList = Arrays.asList(2,4,1,3);

long count = integerList.stream().count();System.out.println(count);

到此這篇關(guān)于Java入門到精通的學(xué)習(xí)筆記:零基礎(chǔ)如何快速學(xué)會(huì)Java開發(fā)的文章就介紹到這了,更多相關(guān)Java實(shí)用學(xué)習(xí)筆記內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 如何優(yōu)雅的處理Spring Boot異常信息詳解

    如何優(yōu)雅的處理Spring Boot異常信息詳解

    這篇文章主要給大家介紹了關(guān)于如何優(yōu)雅的處理Spring Boot異常信息的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 淺談MyBatis-Plus學(xué)習(xí)之Oracle的主鍵Sequence設(shè)置的方法

    淺談MyBatis-Plus學(xué)習(xí)之Oracle的主鍵Sequence設(shè)置的方法

    這篇文章主要介紹了淺談MyBatis-Plus學(xué)習(xí)之Oracle的主鍵Sequence設(shè)置的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • JavaCV實(shí)現(xiàn)讀取視頻信息及自動(dòng)截取封面圖詳解

    JavaCV實(shí)現(xiàn)讀取視頻信息及自動(dòng)截取封面圖詳解

    javacv可以幫助我們?cè)趈ava中很方便的使用OpenCV以及FFmpeg相關(guān)的功能接口。本文將利用Javacv實(shí)現(xiàn)在視頻網(wǎng)站中常見(jiàn)的讀取視頻信息和自動(dòng)獲取封面圖的功能,感興趣的可以了解一下
    2022-06-06
  • SpringBoot切面實(shí)現(xiàn)token權(quán)限校驗(yàn)詳解

    SpringBoot切面實(shí)現(xiàn)token權(quán)限校驗(yàn)詳解

    這篇文章主要介紹了SpringBoot切面實(shí)現(xiàn)token權(quán)限校驗(yàn)詳解,要實(shí)現(xiàn)權(quán)限校驗(yàn),首先數(shù)據(jù)表和實(shí)體類上需要有權(quán)限字段,我的表中permission和gender是通過(guò)外鍵約束permission表和gender表實(shí)現(xiàn)枚舉的,因?yàn)榭赏卣剐愿?需要的朋友可以參考下
    2024-01-01
  • 解決mybatisplus MetaObjectHandler 失效的問(wèn)題

    解決mybatisplus MetaObjectHandler 失效的問(wèn)題

    本文主要介紹了解決mybatisplus MetaObjectHandler 失效的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • Java實(shí)現(xiàn)List分組的常見(jiàn)方法詳解

    Java實(shí)現(xiàn)List分組的常見(jiàn)方法詳解

    這篇文章主要為大家詳細(xì)介紹了使用Java實(shí)現(xiàn)List分組的幾個(gè)常見(jiàn)方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-12-12
  • Spring事件監(jiān)聽器ApplicationListener的使用與原理分析

    Spring事件監(jiān)聽器ApplicationListener的使用與原理分析

    文章介紹了Spring中的事件監(jiān)聽器和事件發(fā)布機(jī)制,包括內(nèi)置事件的使用和自定義事件的創(chuàng)建與發(fā)布,以及如何使用@EventListener注解進(jìn)行事件監(jiān)聽,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2025-11-11
  • 基于Spring Boot 的小區(qū)人臉識(shí)別與出入記錄管理系統(tǒng)功能

    基于Spring Boot 的小區(qū)人臉識(shí)別與出入記錄管理系統(tǒng)功能

    文章介紹基于SpringBoot框架與百度AI人臉識(shí)別API的小區(qū)出入管理系統(tǒng),實(shí)現(xiàn)自動(dòng)識(shí)別、記錄及查詢功能,涵蓋技術(shù)選型、數(shù)據(jù)模型設(shè)計(jì)、接口開發(fā)與系統(tǒng)優(yōu)化方案,為智慧社區(qū)提供高效安全管理工具,感興趣的朋友跟隨小編一起看看吧
    2025-08-08
  • 詳解springboot中各個(gè)版本的redis配置問(wèn)題

    詳解springboot中各個(gè)版本的redis配置問(wèn)題

    這篇文章主要介紹了詳解springboot中各個(gè)版本的redis配置問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Spring Boot分層架構(gòu)詳解之從Controller到Service再到Mapper的完整流程(用戶管理系統(tǒng)為例)

    Spring Boot分層架構(gòu)詳解之從Controller到Service再到Mapper的完整流程(用戶管理

    本文將以一個(gè)實(shí)際案例(用戶管理系統(tǒng))為例,詳細(xì)解析 Spring Boot 中 Controller、POJO、Mapper、Service、ServiceImpl 等層的關(guān)系,并展示從前端發(fā)送請(qǐng)求到后端處理的完整流程,感興趣的朋友跟隨小編一起看看吧
    2025-09-09

最新評(píng)論

藁城市| 泉州市| 蛟河市| 敖汉旗| 亳州市| 山西省| 望奎县| 和田市| 长汀县| 佛学| 中西区| 富民县| 郁南县| 兴宁市| 苏尼特左旗| 闽侯县| 慈利县| 南木林县| 清涧县| 布尔津县| 蓝田县| 额敏县| 蕲春县| 罗甸县| 吴忠市| 垣曲县| 金昌市| 托里县| 禄丰县| 沅陵县| 瓮安县| 宜城市| 泗水县| 峨山| 贵南县| 温宿县| 江口县| 南丹县| 通山县| 洛南县| 潜江市|