Java基礎全程複習筆記(值得參考)

来源:https://www.cnblogs.com/deyo/archive/2023/03/19/17232296.html
-Advertisement-
Play Games

Java基礎複習筆記 第01章:Java語言概述 1. Java基礎學習的章節劃分 第1階段:Java基本語法 Java語言概述、Java的變數與進位、運算符、流程式控制制語句(條件判斷、迴圈結構)、break\continue、 IDEA開發工具的使用、數組 第2階段:面向對象編程(基礎、進階、高級) ...


Java基礎複習筆記

第01章:Java語言概述

1. Java基礎學習的章節劃分

第1階段:Java基本語法
Java語言概述、Java的變數與進位、運算符、流程式控制制語句(條件判斷、迴圈結構)、break\continue、
IDEA開發工具的使用、數組

第2階段:面向對象編程(基礎、進階、高級)

第3階段:Java高級應用
異常處理、多線程、集合框架、File類與IO流、網路編程、日期相關的API與比較器、反射、Java8-17新特征

語言 = 語法 + 邏輯

2. 電腦的構成

  • 硬體:CPU、記憶體、硬碟、輸入設備、輸出設備、數據機
  • 軟體

3. 軟體

  • 軟體:即一系列按照特定順序組織的電腦數據指令的集合。
    • 系統軟體應用軟體之分。
      • 系統軟體:windows、mac os、android、ios、linux
      • 應用軟體:qq、微信、音樂播放器等

4. 人機交互方式

  • 圖形化界面的方式

  • 命令行的方式交互

  • DOS命令(掌握)

    • cd cd.. cd/ md rd del exit cls等

5. 語言

  • 電腦語言的分代

    • 第1代:機器語言:0和1
    • 第2代:彙編語言:出現了助記符
    • 第3代:高級語言:
      • 面向過程階段:C
      • 面向對象階段:C++,Java,C#,Python,JS等
  • 沒有“最好”的語言,只有在特定場景下相對來說,最適合的語言而已。

6. Java概述

  • Java簡史

    • 1995誕生
    • 1996:jdk1.0版本
    • 2004:Java5.0(jdk1.5)--->里程碑式的版本;J2SE->JavaSE、J2EE->JavaEE、J2ME->JavaME
    • 2014:Java8.0--->里程碑式的版本;目前,市場占有率仍然很高。(lambda表達式、StreamAPI)
    • 後續:Java11、Java17都屬於LTS(長期支持版本)
  • SUN、Oracle、Google等

  • Java之父:詹姆斯·高斯林

  • Java的應用場景:

    • JavaSE:開發桌面級應用 (不靠譜)
    • JavaEE:開發企業級後臺應用
    • JavaME:開發小型設備的應用(不靠譜)

​ ----> JavaEE、Android應用、大數據開發

7. JDK的下載、安裝及環境變數的配置(重點)

  • jdk下載:官網下載
  • 安裝:jdk8.0和jdk17.0 (傻瓜式安裝)
  • path環境變數的配置(重點)

8. 第1個Java程式

新建java文件:PersonInfo.java

class PersonalInfo{
    public static void main(String[] args){
        System.out.println("姓名:家琪琪\n");
        //System.out.println();//換行操作
        System.out.println("性別:女"); 
        System.out.println("住址:成都青創園"); 
    }
    
}

針對於第1個程式的小結及常見問題的分析


1. HelloWorld程式如下:編寫在HelloWorld.java文件中
class HelloJava{
	public static void main(String[] args){
		System.out.println("HelloWorld!!");
		System.out.println("HelloWorld!!");
		System.out.println("你好,世界!");
	}

}


2. Java程式要想執行成功,需要如下的三個步驟:
第1步:編寫:將java源代碼編寫在.java結尾的源文件中。
第2步:編譯:針對於編寫好的源文件進行編譯操作。格式:javac 源文件名.java
             編譯以後,會生成一個或多個.class結尾的位元組碼文件。位元組碼文件的名稱即為源文件中對應的類名
第3步:運行:針對於編譯好的位元組碼文件,進行解釋運行操作。格式: java 位元組碼文件名  或  java 類名



3. 針對於編寫過程來說:
3.1 class:是一個關鍵字,小寫,後面跟著一個類名。
3.2 編寫的類或方法必須使用一對{}。
3.3 
> main()作為程式的入口出現!格式如下:
    public static void main(String[] args)
> main()的格式是固定的!大家剛開始學習,可以"死記硬背"一下。
> 但是,可以考慮修改為如下的格式:
  方式1:public static void main(String args[])
  方式2:public static void main(String[] a)   args:是arguments的縮寫

3.4 輸出語句的編寫:
> System.out.println(123);  表示:輸出123之後換行

> System.out.print(123);    表示:輸出123之後不需換行


3.5 編譯過程中的小結:
> 編譯源文件。此時要求在源文件所在的路徑下執行"javac 源文件名.java"的操作

可能編譯時報錯的情況:
情況1:如果源文件名寫錯(不包括大小寫不同的情況)或者不是在源文件所在的路徑下執行javac操作則會報錯。
情況2:編寫的程式中有非法的語法或非法的字元。
    > 缺少必要的大括弧、大小寫的問題(Java是嚴格區分大小寫的)、出現的標點符號必須是英文格式下的

3.6 解釋運行過程的小結:
> 針對於位元組碼文件對應的類,執行java.exe命令。格式:java 類名。
> 此操作需要在位元組碼文件所屬的路徑下執行。

可能運行時報錯的情況:
情況1:執行位元組碼文件所在的路徑不對或位元組碼文件的名寫錯了(註意,java嚴格區分大小寫,如果大小寫出錯了,仍然認為文件名寫錯了)。
情況2:可以出現運行時異常(放到第9章中講解)


3.7 說明
1. Java是嚴格區分大小寫的
2. 每一行執行語句必須以;結尾
3. 程式在編寫過程中,為了可讀性更強,增加必要的縮進,使用tab鍵即可。
4. 一個源文件中可以聲明一個或多個類。
   一個源文件中最多只能有一個類聲明為public。
   聲明為public的類的類名必須與源文件名相同。

9. 註釋

  • 掌握:單行註釋、多行註釋
    • 作用1:對程式中的代碼進行解釋說明
    • 作用2:有助於調試程式
  • 熟悉:文檔註釋 (可以被javadoc解析)

10. API文檔

  • API:(Application Programming Interface,應用程式編程介面)是 Java 提供的基本編程介面。
    • 像String、System都屬於API
  • API文檔:用於解釋說明API如何使用的一個文檔。

第02章:變數與進位

1. 關鍵字(keyword)

  • 關鍵字:被Java語言賦予特殊含義的字元串。
  • 註意點:關鍵字都是小寫的!
  • Java規範了50個關鍵字(包含了goto、const兩個保留字)
    • 額外的三個字面量true、false、null雖然不是關鍵字,但是我們也把他們看做是關鍵字。

2. 標識符

  • 凡是可以自己命名的地方,都是標識符。
  • 標識符都有哪些位置?類名、變數名、包名、方法名、介面名、常量名等
  • 標識符的命名規則

(如果不遵守,編譯不通過。要求大家遵守)

由26個英文字母大小寫,0-9 ,_或 $ 組成
數字不可以開頭。
不可以使用關鍵字和保留字,但能包含關鍵字和保留字。
Java中嚴格區分大小寫,長度無限制。
標識符不能包含空格。

  • 標識符的命名規範

(如果不遵守規範,不影響程式的編譯和運行。建議大家遵守,否則容易被鄙視)

包名:多單片語成時所有字母都小寫:xxxyyyzzz。
例如:java.lang、com.atguigu.bean

類名、介面名:多單片語成時,所有單詞的首字母大寫:XxxYyyZzz
例如:HelloWorld,String,System等

變數名、方法名:多單片語成時,第一個單詞首字母小寫,第二個單詞開始每個單詞首字母大寫:xxxYyyZzz
例如:age,name,bookName,main,binarySearch,getName

常量名:所有字母都大寫。多單詞時每個單詞用下劃線連接:XXX_YYY_ZZZ
例如:MAX_VALUE,PI,DEFAULT_CAPACITY

  • 標識符在聲明時,要見名知意!

3. 變數的基本使用

  1. 記憶體中的一個存儲區域,該區域的數據可以在同一類型範圍內不斷變化
  2. 變數的構成包含三個要素:數據類型 變數名 變數值
  3. Java中變數聲明的格式:數據類型 變數名 = 變數值;
  4. Java是一門強類型的語言。即每一個變數都規定了具體的類型。
  5. 使用變數註意:
    • Java中每個變數必須先聲明,後使用。
    • 使用變數名來訪問這塊區域的數據。
    • 變數的作用域:其定義所在的一對{ }內。
    • 變數只有在其作用域內才有效。出了作用域,變數不可以再被調用。
    • 同一個作用域內,不能定義重名的變數。

4. 基本數據類型的變數

變數按照數據類型來分:

基本數據類型:整型(byte \ short \ int \ long ) 、浮點型(float \ double ) 、字元型char 、布爾型boolean

引用數據類型:類(class)、介面(interface)、數組(array); 註解(annotation)、枚舉(enum)、記錄(record)
  • 整型變數
//1. 整型的使用:
//byte(1個位元組=8bit,-128~127) \ short(2位元組) \ int(4位元組) \ long(8位元組)

byte b1 = 12;

b1 = 127;
//①聲明變數以後,給變數賦的值必須在變數類型所允許的範圍內變化。
//b1 = 128;//因為超出了byte的範圍,所以報錯

//② 給long類型變數賦值時,要求以"l"或"L"結尾
short s1 = 123;
int i1 = 1234;
long l1 = 12313123L;
System.out.println(l1);

//③ 實際開發中,如果沒有特殊需求的話,推薦大家使用int類型來定義整型變數。

//④ 預設情況下,整型常量都是int類型
//int i2 = i1 + 2;
		
  • 浮點類型
//2. 浮點型的使用:
// float(4位元組)  / double (8位元組)
//① float雖然占用的空間比long小,但是表數範圍比long大,進而float精度不高。

//② 給float類型變數賦值時,要求以"f"或"F"結尾。否則,編譯不通過
double d1 = 123.456;
//d1 = 123.456456456456456456; //體會double的精度也有限
System.out.println(d1);

float f1 = 123.456f;
System.out.println(f1);

//③ 實際開發中,如果沒有特殊需求的話,推薦大家使用double類型來定義浮點型變數。

//④ 預設情況下,浮點型常量都是double類型
double d2 = d1 + 12.34; //12.34是常量,是double類型
  • char類型(字元類型)
//3.字元類型的使用:char (2位元組)
//① 一般情況下,我們使用一對''表示一個具體的字元。
//說明:char定義變數的話,''內有且只能有一個字元
char c1 = 'a';

//編譯不通過
//char c2 = '';
//char c3 = 'ab';

//② char類型變數的定義方式
//方式1:最常見的方式
char c4 = '中';
char c5 = '1';
char c6 = 'す';

//方式2:直接使用Unicode值來表示字元型常量
char c7 = '\u0023';
System.out.println(c7);

//方式3:使用轉義字元
char c8 = '\n';
char c9 = '\t';
System.out.println("hello" + c8 + "world");
System.out.println("hello" + c9 + "world");

//方式4:使用字元對應的ascii碼值進行賦值
char c10 = 'a';
System.out.println(c10 + 1);

char c11 = 97;
System.out.println(c10 == c11);//true
  • 布爾類型(boolean)
//① 不談boolean占用記憶體空間的大小
//② boolean類型只能取兩個值之一:true 、 false
boolean b1 = true;
boolean b2 = false;

//③ 開發中,我們常常在if-else結構、迴圈結構中使用boolean類型
boolean isMarried = false;
if(isMarried){
    System.out.println("很遺憾,不是單身了");
}else{
    System.out.println("不錯,可以多談幾個女朋友了");
}

5. 基本數據類型變數間的運算規則

5.1 自動類型提升規則

byte、short、char ---> int ---> long ---> float ---> double

說明:
① 容量小的變數和容量大的變數做運算時,運算的結果是容量大的變數的數據類型。
(此時的容量小、容量大指的是存儲數據的範圍的大小,並非占用記憶體空間的大小。比如:float的容量要大於long的容量)
② byte、short、char 三者之間的變數做運算,結果是int類型。

③ 不管是自動類型提升規則,還是強制類型轉換規則都只針對於基本數據類型中的7種進行操作(除了boolean類型)

5.2 強制類型轉換規則

說明:

①看做是自動類型提升規則的逆運算

② 如果需要將容量大類型的變數轉換為容量小的類型的變數時,就需要使用強制類型轉換
③ 強制類型轉換需要使用一對()表示
④ 使用強轉符轉換時,可能造成精度的損失

6. String與8種基本數據類型變數間的運算

  1. String的理解

String,即為字元串類型。
聲明String類型的變數,可以使用一對""表示。
一對""內可以聲明0個、1個或多個字元

  1. String與基本數據類型變數間的運算

String類型是可以與8種基本數據類型的變數做運算的。
String只能與8種基本數據類型的變數做連接運算:+
連接運算的結果只能是String類型。

7. 進位(瞭解)

  • 電腦中存儲和運算的所有數據都要轉為二進位。包括數字、字元、圖片、聲音、視頻等。

7.1 常見的幾種進位

  • 熟悉:

    • 十進位(decimal)

      • 數字組成:0-9
      • 進位規則:滿十進一
    • 二進位(binary)

      • 數字組成:0-1
      • 進位規則:滿二進一,以0b0B開頭
    • 八進位(octal):很少使用

      • 數字組成:0-7
      • 進位規則:滿八進一,以數字0開頭表示
    • 十六進位

      • 數字組成:0-9,a-f
      • 進位規則:滿十六進一,以0x0X開頭表示。此處的 a-f 不區分大小寫

7.2 二進位與十進位間的轉換

熟悉:二進位與十進位間的轉換(見ppt)

  • 表示二進位整數時,最高位為符號位。0:正數;1:負數。

  • 二進位整數在存儲時,涉及到原碼、反碼、補碼。

    • 正數:三碼合一。

    • 負數:負數的原碼,除符號位外,各個位取反,得到負數的反碼。

      ​ 負數的反碼+1,得到負數的補碼。

  • 電腦底層都是以二進位補碼的形式存儲數據的。

7.3 二進位與其它進位間的轉換

  • 瞭解:二進位與八進位、十六進位間的轉換

第03章:IDEA的安裝與使用

1. 認識IDEA的地位、特點

  • Java開發中占比第1。
  • Eclipse?IDEA?① 符合人體工程學 ② 功能強大

2. IDEA的下載、安裝、註冊

3. IDEA的基本使用

  • 在IDEA中能創建一個工程:Project。
    • 在工程的src下寫一個HelloWorld,並運行
  • 安裝課件中的第5節中的設置,作必要的修改。

4. 熟悉工程、module中jdk和設置語言級別操作

image-20230206092214934

關於工程:

image-20230206092341586

關於Module:

image-20230206092418306

添加SDK:

image-20230206092456737

5. 熟悉Project-Module-Package-Class的關係

  • 上一級和下一級之間是一對多的關係。
  • 掌握:新建Project、新建Module、刪除Module、導入老師的Module(難點)

6. 關於IDEA的其它操作

  • 模板的使用
  • 快捷鍵的使用
  • Debug程式
  • 插件的使用

第04章:運算符與流程式控制制

1. 運算符之1:算術運算符

+ -  + - * / %  ++  --  +
  • % : 結果與被模數的符號相同。常用來判別是否能整除一個數。
  • (前)++ 與 (後)++ ;(前)-- 與 (後)--

2. 運算符之2:賦值運算符

=  +=  -=   *=  /=   %=
  • = : 與 == 的區別。= 的右邊是變數或常量。"連續賦值" (int i,j;i = j = 10;)
  • += -= *= /= %= :運算後,不會改變變數的類型。(int i = 1; i *= 0.1; )

3. 運算符之3:比較運算符

>  <   >=   <=   
==  != 
  • > < >= <= 只能適用於7種基本數據類型(不含boolean)
  • == != 適用於8種基本數據類型、引用數據類型。
  • 比較運算符的結果是boolean類型。

4. 運算符之4:邏輯運算符

&  &&  |  || ^  !
  • 邏輯運算符操作的是boolean類型,結果也是boolean類型
  • & 與 && 的區別;| 與 || 的區別

5. 運算符之5:位運算符(非重點)

<<  >>  >>>   
&  |  ^   ~
  • 位運算符操作的整數類型
  • << >> >>>的應用場景

6. 運算符之6:條件運算符

  1. (條件表達式)? 表達式1 : 表達式2

  2. 規則:

判斷條件表達式是true還是false,如果是true,則執行表達式1;如果是false,則執行表達式2
如果將運算的結果賦給一個變數的話,要求:表達式1與表達式2的類型一致。(相同 或 滿足自動類型提升的規則即可)

  1. 案例:獲取兩個數的較大值;獲取三個數的最大值
  2. 與分支結構的if-else對比:

凡是可以使用條件運算符的地方,都可以改寫為if-else。反之,不一定。
在既可以使用條件運算符,又可以使用if-else的場景下,推薦使用條件運算符。因為條件運算符效率稍高。

7. 運算符的優先順序

  • 我們在開發中,如果希望某個運算符優先運算的話,主動的添加一對()。

  • 常見的一些運算符優先順序誰高誰低呢?基本上是如你所想

    int x = 10;
    boolean y = false;
    if(x++ == 10 && y = true){...}
    
  • 大家在開放時,如果涉及到多個運算符做運算,建議可以分行寫

8. 流程式控制制語句概述

順序結構:略,即代碼從上往下依次執行

分支結構:if-else 、 switch-case

迴圈結構:for、while、do-while
        foreach放到集合章節中講解

9. 分支結構1:if-else

  • 格式
格式1:
if(條件表達式){
  	語句塊;
}

格式2:"二選一"
if(條件表達式) {
  	語句塊1;
}else {
  	語句塊2;
}

格式3:"多選一"
if (條件表達式1) {
  	語句塊1;
} else if (條件表達式2) {
  	語句塊2;
}
...
}else if (條件表達式n) {
 	語句塊n;
} else {
  	語句塊n+1;
}
  • 說明
說明1:
> 如果多個條件表達式之間是"互斥"關係(或沒有交集的關係),則多個條件表達式誰寫在上面,誰寫在下麵都可以。
> 如果多個條件表達式之間是包含關係,則通常需要將條件表達式範圍小的聲明在條件表達式範圍大的上面。

說明2:
> 我們可以在程式使用if-else的嵌套結構
> 如果if-else中一對大括弧內的語句塊只有一行執行語句,則此一對大括弧可以省略。但是,不建議大家省略!

說明3:
> 開發中,在一些具體的題目中,可以在if-else if -else if -... -else 結構中省略else結構。

10. 分支結構2:switch-case

  • 格式
switch(表達式){
    case 常量值1:
        語句塊1;
        //break;
    case 常量值2:
        語句塊2;
        //break;
    // ...
   [default:
        語句塊n+1;
        break;
   ]
}
  • 說明
1. switch-case的執行過程:
根據switch中表達式的值,依次匹配一對{}內的case結構。一旦表達式與某個case的常量值相等,則執行此case中的語句塊。
執行完此語句塊之後,如果此case中包含break,則結束當前switch-case結構。
                如果此case中不包含break,則會繼續執行其後的case中的語句塊(case穿透的場景)。直到遇到break或執行完default,才會結束switch-case結構。

2. 說明:
> 在switch-case結構中可以使用break關鍵字,一旦執行,表示終止(或退出)當前switch-case結構。
> 開發中,在使用switch-case的場景中,不加break的情況要多於加break的情況。
> switch中的表達式只能是特定的如下類型的變數:
   byte \ short \ char \ int ; 枚舉類型(jdk5.0新增) \ String(jdk7.0新增)
> case後的常量值,需要與switch中表達式的值進行==的判斷。如果返回true,則執行此case中的語句塊。返回false,則不執行。
> default類似於if-else結構中else。 可選的,且位置是靈活的。
  • if-else 與 switch-case的對比
> 針對的變數的類型來講,if-else沒有限制,而switch-case有類型的限制,且建議case匹配的情況有限、不多的場景。
> 二者的轉換:凡是使用switch-case結構的,都可以轉換為if-else。反之,不成立。
> 開發中,在既可以使用switch-case,又可以使用if-else的情況下,推薦使用switch-case。因為其效率稍高。
> if-else的主要優勢:涉及到任何的分支結構,都可以使用if-else實現
  switch-case的主要優勢:在可以使用if-else和switch-case的情況下,效率稍高。
                       case穿透。

11. 迴圈結構1:for

  • 迴圈的概述
凡是迴圈結構,都有如下的4個要素:
> ① 初始化條件部分
> ② 迴圈條件部分  -->是boolean類型
> ③ 迴圈體部分
> ④ 迭代條件部分
  • 格式
for(①;②;④){
    ③
}

執行過程:① - ② - ③ - ④ - ② - ③ - ④ - ...- ②
  • 說明
1. 註意:迴圈條件部分必須是boolean類型。

2. break關鍵字的使用
> break可以使用在迴圈結構中 (複習:還可以使用在switch-case中)
> 一旦執行,就跳出當前迴圈結構。

12. 迴圈結構2:while

  • 格式
①
while(②){
	③
	④
}
  • 執行過程
① - ② - ③ - ④ - ② - ③ - ④ - ...- ②
  • 說明
for迴圈和while迴圈一定可以相互轉換。
for、while迴圈的區別:初始化條件的作用域不同。while迴圈的初始化條件在while迴圈結束後,仍然有效。

13.迴圈結構3:do-while

  • 格式
①
do{
	③
	④
}while(②);
  • 執行過程
① - ③ - ④ - ② - ③ - ④ - 。。。- ②
  • 說明
do-while相較於其他迴圈的區別:至少執行一次迴圈體。
在迴圈條件第1次判斷時,如果是true的情況下,三個迴圈結構可以相互轉換的。
  • 使用場景
for迴圈:有明確的迴圈、遍歷次數時。比如:遍歷100以內的自然數、遍曆數組
while迴圈:沒有明確的迴圈、遍歷的次數時。比如:使用迭代器遍歷集合。
do-while迴圈:確保至少執行一次。

14. "無限"迴圈

  • 結構
while(true) 、 for(;;)
  • 使用場景
不確定迴圈的次數時,使用此結構
  • 結束迴圈的方式
在迴圈內部,滿足某個條件的情況下,執行break。
  • 註意:必須確保此迴圈可以結束。否則就是死迴圈!我們開發中要避免死迴圈

15. 嵌套迴圈

  • 格式
外層迴圈{
	內層迴圈{
	
	}
}
  • 說明:上述的外層迴圈、記憶體迴圈可以是for、while、do-while

  • 技巧:

    • 外層迴圈執行m次,內層迴圈執行n次。意味著內層迴圈的迴圈體執行 m * n次
    • 外層控制行數,內層控制列數

16. break、continue關鍵字的使用

相同點:① 都可以使用在迴圈結構中 ② 其後不能編寫執行語句

不同點:① 結束迴圈結構;結束當次迴圈 ②使用範圍:break:switch-case結構中使用

17. Scanner的使用、隨機數的獲取

  • Scanner的使用
1. 如何從鍵盤獲取數據? 使用Scanner類

2. 如何使用Scanner類,從鍵盤獲取數據呢? (掌握)
    步驟1:導包
    import java.util.Scanner

    步驟2:創建Scanner的對象(或實例)
    Scanner scanner = new Scanner(System.in);

    步驟3:通過Scanner的對象,調用Scanner類中聲明的方法,從鍵盤獲取指定類型的變數
    scanner.nextXxx()

    步驟4:關閉Scanner
    scanner.close();
    
3. Scanner類中提供瞭如下的獲取不同類型變數的方法:
獲取byte: nextByte();
獲取short: nextShort();
獲取int: nextInt();
獲取long: nextLong();
獲取float: nextFloat();
獲取double: nextDouble();
獲取boolean: nextBoolean();

註意,沒有提供獲取字元的方法。我們可以通過獲取字元串的方法,來獲取字元。
獲取String: next() / nextLine()。
如何獲取一個字元:next().charAt(0)
  • 如何獲取隨機數
1. 調用Math類中的random(),可以獲取一個[0.0,1.0)範圍內的隨機浮點數。

2. 如何獲取[0,9]範圍的隨機整數:(int)(Math.random() * 10);
    如何獲取[1,10]範圍的隨機整數:(int)(Math.random() * 10) + 1;
    如何獲取[0,100]範圍的隨機整數:(int)(Math.random() * 101);
    如何獲取[10,100]範圍的隨機整數:(int)(Math.random() * 91) + 10;  //[10,100]

    公式:如何獲取[a,b]範圍的隨機整數:(int)(Math.random() * (b - a + 1) + a)

18. 階段項目1:穀粒記賬軟體

第05章:數組

1. 數組的概述(理解)

1. 數組的理解

概念:
數組(Array),是多個相同類型數據按一定順序排列的集合,並使用一個名字命名,
並通過編號的方式對這些數據進行統一管理。

簡稱:多個相同類型的數據的組合

Java中的容器:數組、集合框架(用於存儲不同特點的多個數據)

2. 幾個相關的概念
> 數組名(即為容器的名稱)
> 元素 (即為數組中具體的一個個的數據)
> 數組的長度(容器中元素的個數)
> 數組的角標、下標、下角標、索引、index (即為數組中元素的具體位置。從0開始)

3. 數組的特點:
- 數組本身是`引用數據類型`,而數組中的元素可以是`任何數據類型`,包括基本數據類型和引用數據類型。
- 創建數組對象會在記憶體中開闢一整塊`連續的空間`。占據的空間的大小,取決於數組的長度和數組中元素的類型。
- 數組中的元素在記憶體中是依次緊密排列的,有序的。
- 數組,一旦初始化完成,其長度就是確定的。
- 數組的`長度一旦確定,就不能修改`。
- 我們可以直接通過下標(或索引)的方式調用指定位置的元素,速度很快。
- 數組名中引用的是這塊連續空間的首地址。


4. 複習:變數按照數據類型的分類
4.1 基本數據類型:byte \ short \ int \ long ;float \ double ;char ;boolean
4.2 引用數據類型:類、數組、介面; 枚舉類型、註解類型、記錄類型(Record)

5. 數組的分類
5.1 按照元素的類型:基本數據類型元素的數組、引用數據類型元素的數組
5.2 按照數組的維數來分:一維數組、二維數組、....

2. 一維數組的使用(重點)

(6個基本點)
> 數組的定義:靜態初始化、動態初始化
> 數組元素的表示:使用角標,角標從0開始,到數組的長度-1結束。
> 數組的長度:length
> 遍曆數組:for迴圈
> 數組元素的預設值:記住。後續類中屬性的預設值也如此。
> 數組的記憶體解析(難點)---> 具體圖示見chapter06章節的module中即可。

3. 二維數組的使用(熟悉)

  • 二維數組的理解
> 角度1:一個一維數組又作為了另一個數組arr的元素。則數組arr就稱為二維數組。
> 角度2:一個數組arr1的元素,仍是是一個數組,則arr1稱為二維數組
     > 數組,屬於引用數據類型;數組的元素也可以是引用數據類型。--> 數組的元素,還可以是數組。

> 說明:其實Java中不存在二維、三維、..數組,只是將一個上述的arr或arr1稱為是二維數組。

> 區分:外層元素、內層元素
  • 基本內容
二維數組的使用(6個基本點)
> 數組的定義
> 數組元素的調用
> 數組的長度
> 數組的遍歷
> 數組元素的預設初始化值(稍難)
> 數組的記憶體解析(難點)---> 具體圖示見chapter06章節的module中即可。
  • 數組元素的預設值
1. 二維數組元素的預設初始化值
1.1 動態初始化方式1:(比如:int[][] arr = new int[3][4])

外層元素:存儲的是地址值。(具體來說,就是外層元素指向的一維數組的地址值)


內層元素:與一維數組元素的預設值相同。
    > 整型:0
    > 浮點型:0.0
    > 字元型:0 或 '\u0000'
    > 布爾型:false
    > 引用類型:null


1.2 動態初始化方式2:(比如:int[][] arr = new int[3][])
外層元素:null
內層元素:不存在。一旦調用會報異常(NullPointerException)

4. 數組的常用演算法(熟練)

  • 演算法常用操作1
1. 數值型數組特征值統計
這裡的特征值涉及到:平均值、最大值、最小值、總和等

2. 數組元素的賦值(實際開發中,遇到的場景比較多)

3. 數組的複製、賦值

4. 數組的反轉
  • 演算法常用操作2
1. 數組的擴容與縮容

2. 數組元素的查找(或搜索)
順序查找:
    > 優點:簡單,好理解,數組沒有任何的前提限制。(比如:有序)
    > 缺點:相較於二分法查找更慢一些。

二分法查找:
    > 優點:相較於順序查找,更快。O(logN)
    > 缺點:必須此數組有序。
    
3. 排序演算法
3.1 排序演算法的衡量標準:
> 時間複雜度:更為關心的標準。
    Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n^2)<Ο(n^3)<…<Ο(2^n)<Ο(n!)<O(n^n)。
> 空間複雜度:常出現以空間換時間的做法。

> 穩定性

3.2 排序的分類:內部排序、外部排序

內部排序的具體演算法:十種。

我們需要關註的幾個排序演算法:
> 冒泡排序:簡單、容易實現;企業筆試中容易考。時間複雜度:O(n^2)。要求大家可以手寫。
> 快速排序:快速、開發中需要排序情況下的首選。時間複雜度:O(nlogn)。要求大家至少可以說明其實現思路。

5. Arrays:數組的工具類(熟悉)

1. Arrays類所在位置
java.util.Arrays

2. 作用:
封裝了針對數組的常用操作。比如:排序、二分查找、比較數組是否相等、遍歷等。

3. 常用方法:
sort(int[] arr) / binarySearch(int[] arr,int target) / toString(int[] arr)

6. 小結:數組中的常見異常

1. 數組的使用中常見的異常小結
> ArrayIndexOutOfBoundsException:數組角標越界異常

> NullPointerException:空指針異常


2. 出現異常會怎樣?如何處理?

> 一旦程式中出現異常,且沒有處理的情況下,程式就終止執行。

> 目前大家編程時,如果出現上述異常。回來根據異常的提示,修改代碼,確保後續運行不再出現。

第06章:面向對象-基礎

面向對象內容的三條主線:
> 類及類的內部成員:屬性、方法、構造器;代碼塊、內部類
> 面向對象的三大特征:封裝性、繼承性、多態性
> 其它關鍵字的使用:package、import、this、super、static、final、abstract、interface等

1. 理解:面向過程vs面向對象

簡單的語言描述二者的區別
> 面向過程:以`函數`為組織單位。是一種“`執行者思維`”,適合解決簡單問題。擴展能力差、後期維護難度較大。

> 面向對象:以`類`為組織單位。是一種“`設計者思維`”,適合解決複雜問題。代碼擴展性強、可維護性高。

2.2 二者關係:在面向對象的編程中,具體的方法中,仍然會體現面向過程的思想。所以二者是合作關係。

2. 面向對象的要素:類、對象

  • 區分類與對象

    • 類:抽象的、概念上的定義
    • 對象:具體的,實實在在存在的,由類派生出來的
  • 設計類,就是設計類的成員:屬性、方法

  • 面向對象完成具體功能的操作的三步流程(非常重要)

    步驟1:創建類,即設計類的內部成員(屬性、方法)
    步驟2:創建類的對象。
    步驟3:通過"對象.屬性" 或 "對象.方法"的方式,完成相關的功能。
    
  • 對象的記憶體解析

    • JVM記憶體分配:虛擬機棧、堆、方法區(目前用不到)、程式計數器(略)、本地方法棧(略)
      • 虛擬機棧:存放的是方法對應的棧幀,每個棧幀中存放方法中聲明的局部變數。
      • 堆:new出來的"東西":數組實體、對象實體(含成員變數)
    • 創建類的1個對象、創建類的多個對象(記憶體解析圖建議大家都自己畫畫)

3. 類的成員之一:屬性(重點)

1.變數的分類:
- 角度一:按照數據類型來分:基本數據類型(8種)、引用數據類型(數組、類、介面;註解、枚舉、記錄)
- 角度二:按照變數在類中聲明的位置來分:成員變數、局部變數

2. 成員變數的幾個稱謂:

成員變數 <=> 屬性 <=> field(欄位、域)

3. 區分成員變數   vs 局部變數
3.1 相同點:(瞭解)
> 都有三個要素(數據類型、變數名、變數值)
> 聲明的格式相同:數據類型 變數名 = 變數值
> 變數都是先聲明後使用
> 變數都有作用域,在其作用域內是有效的

3.2 不同點:
① 類中聲明的位置的不同:
> 成員變數:聲明在類內部、方法等結構的外部。
> 局部變數:聲明在方法內部、方法的形參、構造器的內部、構造器的形參、代碼塊的內部等

② 在記憶體中分配的位置不同:
> 成員變數:隨著對象實體在堆空間進行分配而分配(或存儲)
> 局部變數:存儲在棧空間。

③ 生命周期:
> 成員變數:隨著對象的創建而產生,隨著對象的消亡而消亡
> 局部變數:(以方法為例)隨著方法的調用而產生,隨著方法的調用結束而消亡。
      > 拓展:每一個方法的執行,都對應著一個棧幀載入進棧中。局部變數就存儲在每個方法對應的棧幀中。
             當方法執行結束時,對應的棧幀就彈出棧,進而棧幀中的局部變數也彈出,進而消亡。

④ 作用域:
> 成員變數:在整個類的內部是有效的。---> 類的方法中是可以調用類中的成員變數的。
> 局部變數:以方法為例,作用域僅限於方法內部。

⑤ 是否可以有許可權修飾符進行修飾:(超綱)
> 成員變數:可以被不同的許可權修飾符進行修飾。(後面講封裝性時,具體說:private、public、protected、預設)
> 局部變數:不可以被許可權修飾符進行修飾。一旦修飾,編譯不通過。


⑥ 是否有預設值:
> 成員變數:都有預設值
      預設值的情況與不同類型的一維數組的元素的預設值相同。
      > 整型:0
      > 浮點型:0.0
      > 字元型:0
      > 布爾型:false
      > 引用類型:null

> 局部變數:沒有預設值。
   意味著在調用之前必須要顯示賦值。如果不賦值,就報錯。
       > 特別的:方法的形參在方法調用時賦值即可。

4. 類的成員之二:方法(重點)

4.1 方法的使用

1. 使用方法的好處
將功能封裝為方法的目的是,可以實現代碼重用,減少冗餘,簡化代碼。

2. 使用舉例
- Math.random()的random()方法
- Math.sqrt(x)的sqrt(x)方法
- System.out.println(x)的println(x)方法
- new Scanner(System.in).nextInt()的nextInt()方法
- Arrays類中的binarySearch()方法、sort()方法、equals()方法

3. 方法聲明的格式

舉例:public void eat()
     public void sleep(int hour)
     public String getName()
     public String playGame(String game)

格式:
     許可權修飾符  返回值類型 方法名(形參列表){
        方法體
     }

4. 具體的方法聲明的細節

4.1 許可權修飾符:體現此方法被調用時,是否能被調用的問題。(主要放到封裝性的時候講解)
    暫時,大家在聲明方法時,先都使用public修飾即可。

4.2 返回值類型:(難點)
    > 分類:有具體的返回值的類型(指明具體的數據類型) 、 沒有返回值類型(使用void)
    > 情況1:有具體的返回值的類型的要求:既然有返回值的類型,則要求此方法在執行完時,一定要返回
            滿足此類型的一個變數或常量。
            > 內部使用"return 變數(或常量)"的方法,返回數據
    > 情況2:沒有返回值類型:內部就不需要使用return結構了。
            > (難點)其實,我們在此方法中也可以使用return,僅表示結束此方法。

    開發中,設計一個方法時,是否需要設計返回值類型?
       > 根據題目的要求設計。
       > 具體問題具體分析:調用完此方法之後,是否需要一個結果性的數據,供之後使用。如果有必要,就設計有返回值類型的場景即可。

4.3 方法名:屬性標識符,定義時需要滿足標識符的命名規則、規範、"見名知意"。

4.4 形參列表:(難點)
       > 在一個方法的一對小括弧中可以聲明形參列表,形參的個數可以為0個、1個或多個。
       > 如果有形參的話,格式為: (數據類型1 形參名1,數據類型2 形參名2,...)

      開發中,設計一個方法時,是否需要提供形參呢?
         > 根據題目的要求設計。
         > 具體問題具體分析:調用此方法時,是否存在不確定性的數據。如果有,則以形參的方法傳入此不確定的數據。

4.5 方法體:即為調用方法時,執行的代碼。可以使用當前方法聲明的形參,使用類中的成員變數。

5. 註意點
> Java里的方法`不能獨立存在`,所有的方法必須定義在類里。
> 方法內可以使用類中的成員變數
> 方法內不可以定義方法,但是方法內可以調用本類中的其它方法。 ---> 遞歸方法中談方法內自己調用自己。
> 類中不可以定義多個相同的方法。---> 方法的重載

4.2 return關鍵字

1. return的作用
> 作用1:結束當前方法的執行
> 作用2:"return + 變數/常量"結構在方法結束的同時,還可以返回一個數據。

2. 使用註意點:
與break、continue類似,其後不能聲明執行語句。

5. 記憶體的分配使用

5.1 方法調用的記憶體解析

- 形參:方法聲明時,一對小括弧內聲明的參數,簡稱:形參
- 實參:方法調用時,實際賦值給形參的值,稱為:實參

過程概述:
每當調用一個方法時,方法就以棧幀的方法載入進虛擬機棧中。方法中聲明的局部變數存放在棧幀中。
當方法執行結束時,棧幀就會彈出棧。棧幀中存放的局部變數也隨之消亡。

image-20230213092822606

5.2 目前為止,記憶體分析(重要)

  • 基本原則

1、JVM中記憶體劃分

  • 棧:以棧幀為基本單位(每個方法對應一個棧幀);棧幀里存放局部變數。
  • 堆:new 出來的"東西":數組實體(含數組元素)、對象實體(含成員變數)

2、區分清成員變數(類內部、方法外聲明的)、局部變數(方法的形參、方法內定義的變數、構造器內定義的變數、構造器的形參、代碼塊內部等)

3、值傳遞機制:

  • 如果參數是基本數據類型,傳遞的是基本數據類型變數存儲的數據值
  • 如果參數是引用數據類型,傳遞的是引用數據類型變數存儲的地址值

6. 再談方法

6.1 方法的重載(overload )

1. 定義:
在同一個類中,允許存在一個以上的同名方法,只要它們的參數列表不同即可。滿足這樣特點的多個方法彼此之間稱為
方法的重載。

2. 總結為:"兩同一不同":同一個類、相同的方法名;形參列表不同(參數的個數不同,參數的類型不同)
> 重載與否與形參名沒有關係、返回值類型沒有關係、許可權修飾符沒有關係

3. 舉例
> Arrays中的重載的binarySearch(xxx) \ equals(xxx,xxx) \ toString(xxx)
> System.out的多個重載的println();

4. 如何判斷兩個方法是相同的呢?(換句話說,編譯器是如何確定調用的某個具體的方法呢?)
> 在同一個類中,只要兩個方法的方法名相同,且參數列表相同(參數的個數相同且參數類型相同),
   則認為這兩個方法是相同的。
        > 與方法的許可權修飾符、返回值類型、形參名都沒有關係。

> 在同一個類,不能編寫兩個相同的方法的。

後續會講:方法的重寫(overwrite / override)

面試題:方法的重載與重寫的區別?

throw \ throws
Collection \ Collections
final \ finally \ finalize
String \ StringBuffer \ StringBuilder
ArrayList \ LinkedList 
。。。
== 、equals()
抽象類、介面

6.2 可變個數形參的方法

1. 使用場景
JDK5.0的新特性。

如果方法在調用時,參數的類型是確定的,但是參數的個數不確定,則可以考慮使用可變個數形參的方法。

2. 格式:類型 ... 變數名


3. 說明:
> 可變個數形參的方法在調用時,可以傳入0個,1個或多個參數。
> 可變個數形參的方法與參數是其它類型的同名方法構成重載。
> 可變個數形參的方法與參數是同樣類型的數組參數構成的方法,在方法名相同的情況下,不構成重載。即兩個方法不能
  同時存在。
        > 可變個數的形參在編譯器看來就是同一個類型的數組參數
> 規定:可變個數的形參需要聲明在方法形參列表的最後
> 一個方法的形參位置,最多只能有一個可變個數的形參
/*
String sql1 = "update customers set name = ?,salary = ? where id = ?";
String sql2 = "delete from customs where id = ?";

public void update(String sql,Object ... objs){
	//使用可變形參objs中的各個元素值給形參sql中的?賦值
}
*/

6.3方法的參數傳遞機制(難點、重點)

1. 對於方法內聲明的局部變數來說:

> 如果此局部變數是基本數據類型的,則將基本數據類型變數保存的數據值傳遞出去
> 如果此局部變數是引用數據類型的,則將引用數據類型變數保存的地址值傳遞出去


2. 方法的參數的傳遞機制:值傳遞

2.1 概念(複習)
形參:方法聲明時,一對小括弧內聲明的參數,簡稱:形參
實參:方法調用時,實際賦值給形參的值,稱為:實參

2.2 規則
> 如果此形參是基本數據類型的,則將基本數據類型的實參保存的數據值傳遞給形參
> 如果此形參是引用數據類型的,則將引用數據類型的實參保存的地址值傳遞給形參


3. 面試題:Java中的參數傳遞機制是什麼? 值傳遞機制。

6.4 遞歸方法(熟悉)

1. 何為遞歸方法?
方法自己調用自己的現象就稱為遞歸。


2. 遞歸方法分類
直接遞歸、間接遞歸。

3. 使用說明:
- 遞歸方法包含了一種`隱式的迴圈`。
- 遞歸方法會`重覆執行`某段代碼,但這種重覆執行無須迴圈控制。
- 遞歸一定要向`已知方向`遞歸,否則這種遞歸就變成了無窮遞歸,停不下來,類似於`死迴圈`。最終發生`棧記憶體溢出`。

7. 對象數組(難點)

1. 何為對象數組?如何理解?

數組中的元素,如果存儲的是對象的話,則稱此數組為對象數組。

2. 舉例:
String[] arr = new String[10];
arr[0] = "hello";
arr[1] = new String("abc");

Person[] arr1 = new Person[10];
arr1[0] = new Person();

Phone[] arr2 = new Phone[10];

3. 記憶體解析:
數組名(比如:stus)存儲在棧空間
創建的20個學生對象,存儲在堆空間中。學生對象的地址值存儲在數組的每個元素中。

image-20230213093603995

8. 關鍵字:package、import

  • package:包,指明瞭Java中的類、介面等結構所在的包。聲明在文件的首行
  • import:導入。指明在當前類中使用的其它包中的結構。聲明在package下,類的聲明之前。
一、package關鍵字的使用

1. 說明
- package,稱為包,用於指明該文件中定義的類、介面等結構所在的包。
- 一個源文件只能有一個聲明包的package語句
- package語句作為Java源文件的第一條語句出現。若預設該語句,則指定為無名包。以後聲明源文件時,不要使用無名包。
- 包名,屬於標識符,滿足標識符命名的規則和規範(全部小寫)、見名知意
  - 包名推薦使用所在公司功能變數名稱的倒置:com.atguigu.xxx。
  - 大家取包名時不要使用"`java.xx`"包,否則運行會報錯
- 包對應於文件系統的目錄,package語句中用 “.” 來指明包(目錄)的層次,每.一次就表示一層文件目錄。
- 同一個包下可以聲明多個結構(類、介面),但是不能定義同名的結構(類、介面)。不同的包下可以定義同名的結構(類、介面)


2. 包的作用
- 包可以包含類和子包,劃分`項目層次`,便於管理
- 幫助`管理大型軟體`系統:將功能相近的類劃分到同一個包中。比如:MVC的設計模式
- 解決`類命名衝突`的問題 ---> 不同包下可以命名同名的類。
- 控制`訪問許可權` ---> 講了封裝性,大家就清楚了。


二、import關鍵字的使用
- import:導入,後面跟一個具體包下的類或介面等結構。

-為了使用定義在其它包中的Java類,需用import語句來顯式引入指定包下所需要的類。
相當於`import語句告訴編譯器到哪裡去尋找這個類`。

- import語句,聲明在包的聲明和類的聲明之間。

- 如果需要導入多個類或介面,那麼就併列顯式多個import語句即可

- 如果使用`a.*`導入結構,表示可以導入a包下的所有的結構。
  舉例:可以使用java.util.*的方式,一次性導入util包下所有的類或介面。

- 如果導入的類或介面是java.lang包下的,或者是當前包下的,則可以省略此import語句。

- 如果已經導入java.a包下的類,那麼如果需要使用a包的子包下的類的話,仍然需要導入。

- 如果在代碼中使用不同包下的同名的類,那麼就需要使用類的全類名的方式指明調用的是哪個類。

- (瞭解)`import static`組合的使用:調用指定類或介面下的靜態的屬性或方法

9. 面向對象的特征一:封裝性

  • 什麼是封裝性?
在Java實現項目時,將不用功能的代碼封裝進不同的方法。使用Java給我們提供的4種許可權修飾對類及類的內部成員進行修飾。
體現被修飾的結構在調用時的可見性的大小。
  • 如何體現封裝性?
> 舉例1:類中的屬性私有化,提供公共的get()和set()方法,用於獲取或設置此屬性的值。
> 舉例2:如果類中存在一些方法,這些方法只在類的內部使用,不希望對外暴露,則可以將這些方法聲明為私有的。
> 舉例3:單例設計模式。(後面講static的時候說)
  • 為什麼需要封裝性?
-  `高內聚`:類的內部數據操作細節自己完成,不允許外部干涉;
-  `低耦合`:僅暴露少量的方法給外部使用,儘量方便外部調用。


- 通俗的講,把該隱藏的隱藏起來,該暴露的暴露出來。這就是封裝性的設計思想。

10. 類的成員之三:構造器

1. 構造器的理解

體會1: Scanner scan = new Scanner(System.in);
      Person per = new Person();

體會2:
construct : v. 建設、建造
construction: n. 建設、建造    CCB 中國建設銀行  ICBC
constructor : n.建設者,建造者

2. 構造器的作用
>作用1:搭配new關鍵一起,用於對象的創建
>作用2:用於初始化對象中的成員變數

3. 構造器的使用說明
> 一個類中,如果沒有顯式提供構造器的話,則JVM會預設提供一個空參的構造器。(其許可權修飾符與類的許可權修飾符相同)
> 聲明格式:許可權修飾符 類名(形參列表){}
> 一個類的多個構造器,彼此構成重載
> 如果一個類中,一旦顯式的聲明瞭構造器,則JVM不再提供預設的空參的構造器了。
> 結論:凡是類,都有構造器(自始至終都是對的)

11. 其它幾個小知識

11.1 類中實例變數的賦值位置及順序

0.實例變數:屬於屬性(或成員變數),不使用static修飾即可。

1. 在類的屬性中,可以有哪些位置給屬性賦值?
> ① 預設初始化 ---> 只執行一次
> ② 顯式初始化 ---> 只執行一次
> ③ 構造器中初始化  ---> 只執行一次
*********************************
> ④ 創建對象以後,通過"對象.屬性" 或"對象.方法"的方式,給屬性賦值  ---> 可以多次執行


2. 這些位置執行的先後順序是怎樣?
① - ② - ③ - ④



3. 以上操作在對象創建過程中可以執行的次數如何?
①、②、③:只執行一次
④:可以多次執行

11.2 JavaBean

所謂JavaBean,是指符合如下標準的Java類:
- 類是公共的
- 有一個無參的公共的構造器
- 有屬性,且有對應的get、set方法

11.3 UML類圖

理解

11.4 匿名對象

//匿名對象
System.out.println(new Circle(2.5).findArea());
//知識點1:如上寫法的匿名對象,只能被調用一次。
System.out.println(new Circle(2.5).getRadius());
//知識點2:開發中,常常將匿名對象作為參數傳遞給方法的形參。
Test4_5 test = new Test4_5();

test.show(new Circle(3.4));

第07章:面向對象-進階

1. 關鍵字:this

  • this可以調用屬性、方法;構造器。
    • 記住:this必須使用的場景:屬性與形參同名時;調用重載的構造器

2. 面向對象特征二:繼承性

  • 為什麼需要繼承性?

    • 繼承的出現減少了代碼冗餘,提高了代碼的復用性。
    • 繼承的出現,更有利於功能的擴展。
    • 繼承的出現讓類與類之間產生了is-a的關係,為多態的使用提供了前提。
  • 什麼是繼承性?

    • class B extends A{}

      繼承中的基本概念:

      A類:父類、SuperClass、超類、基類
      B類:子類、SubClass、派生類

  • 繼承性的基本使用

1. 有了繼承性以後:
> 子類繼承父類以後,就獲取了父類中聲明的所有的屬性和方法。 ----> 刻畫是否存在此屬性、方法
  但是,由於封裝性的影響,可能導致子類不能調用。  ----> 刻畫能否調用此屬性、方法

> extends: 繼承。還可以理解為“擴展、延展”。意味著子類在繼承父類的基礎上,還可以擴展自己特有的屬性、方法。
   父類、子類的關係不同於集合、子集的關係。


2. 預設的父類:
如果一個類顯式聲明瞭父類,則其父類為指定聲明的父類。
如果一個類沒有顯式聲明其父類,則預設繼承於java.lang.Object類。

3. 補充說明:
> 一個父類可以被多個子類繼承。
> 一個子類只能聲明一個父類。----> Java中類的單繼承性。
> Java中的類支持多層繼承。
> 子類、父類是相對的概念。
    > 概念:直接父類、間接父類
> Java中的任何類(除了java.lang.Object類)都直接或間接的繼承於java.lang.Object類。

3. 方法的重寫

1. 為什麼需要方法的重寫?

子類繼承父類以後,父類中的方法在許可權允許的情況下,子類可以直接調用。但是我們在一些場景中發現,父類
中的方法不適用於子類。怎麼處理呢?需要使用方法的重寫。

舉例(銀行賬戶):

class Account{ //賬戶
    double balance; //餘額

    //取錢
    public void withdraw(double amt){
        if(balance >= amt){
            balance -= amt;
            System.out.println("取款成功");
        }
    }

    //...
}

class CheckAccount extends Account{  //信用卡賬戶
    double protectedBy; //可透支額度

    //取錢
    public void withdraw(double amt){
        if(balance >= amt){
            balance -= amt;
            System.out.println("取款成功");
        }else if(protectedBy >= amt - balance){
            protectedBy -= amt - balance;
            balance = 0;
            System.out.println("取款成功");
        }else{
            System.out.println("取款失敗");
        }
    }
}


2. 何為方法的重寫?
子類繼承父類以後,對父類中繼承過來的方法進行覆蓋、覆寫的操作。此操作就稱為方法的重寫。


3. 方法重寫應遵循的規則

[複習]方法聲明的格式:許可權修飾符 返回值類型 方法名(形參列表){ 方法體 }

具體規則:稱謂:父類被重寫的方法;子類重寫父類的方法
    > 子類重寫父類的方法 與 父類被重寫的方法的方法名、形參列表相同。
    > 子類重寫父類的方法的許可權修飾符不小於父類被重寫的方法的許可權修飾符
    > 返回值類型:
        > 父類被重寫的方法的返回值類型為void,則子類重寫父類的方法的返回值類型必須為void
        > 父類被重寫的方法的返回值類型為基本數據類型,則子類重寫父類的方法的返回值類型必須為同類型的基本數據類型
        > 父類被重寫的方法的返回值類型為引用數據類型,則子類重寫父類的方法的返回值類型與父類的相同,或是父類的類型的子類。

技巧:建議子類重寫父類的方法時,我們將許可權修飾符、返回值類型都聲明為與父類的方法相同的。

註意點:
> 子類不能重寫父類中聲明為private許可權的方法。

4. 面試題:區分方法的重載(overload)與重寫(override / overwrite)

重載:"兩同一不同"
重寫:子類在繼承父類以後,可以對父類中的同名同參數的方法進行覆蓋、覆寫。此操作即為方法的重寫。
    具體的規則為:....。

4. 關鍵字:super

  • super調用父類的屬性、方法;構造器

    • 使用場景:子父類中出現同名屬性;子類重寫了父類的方法時。

      ​ super調用構造器,體現載入父類的結構。

5. 子類對象實例化的全過程(瞭解)

1. 從結果的角度來看:---->體現為類的繼承性。

當子類繼承父類以後,子類就獲取了父類(直接父類、所有的間接父類)中聲明的所有的屬性、方法。

當我們創建了子類對象以後,在堆空間中就保存了子類本身及其所有的父類中聲明的屬性。同時,子類對象在許可權允許
的情況下,可以調用子類及其所有的父類中聲明的方法。


2. 從過程的角度來看:

當我們通過子類的構造器創建對象時,一定會直接或間接的調用到其直接父類的構造器,其直接父類的構造器同樣會
直接或間接的調用到其父類的構造器,...,以此類推,最終一定會調用到java.lang.Object類的構造器為止。

因為我們調用過所有的父類的構造器,進而所有的父類就需要載入到記憶體中,進而堆空間中就有所有父類中聲明的屬性。
以及可以在許可權允許的情況下,調用父類中聲明的方法。


問題:在創建子類對象的過程中,一定會調用父類中的構造器嗎? yes!



3. 問題:創建子類的對象時,記憶體中到底有幾個對象?
只有1個!

6. 面向對象特征三:多態性

6.1 向上轉型:多態

  • Java中的多態性體現為:子類對象的多態性(狹義上理解)。即父類的引用指向子類的對象。
  • 應用場景:當通過父類的引用調用方法時,實際執行的是子類重寫父類的方法。
  • 好處:多態性常使用在方法的形參位置。多態的出現,極大的減少了方法的重載,同時有利於程式的擴展。
  • 舉例:① equals(Object obj) ② Account - Customer : setAccount(Account acct) ③ 凡是代碼中出現了抽象類、介面,都可以體現為多態性。
  • 共識:Java中的多態性(廣義上理解):1、子類對象的多態性。 2、方法的重寫。

6.2 向下轉型:多態的逆過程

  • Student s = (Student)new Person(); //編譯通過,運行不通過。
  • 如何向下轉型:使用強轉符:()
  • 可能出現的
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • reactive reactive 創建一個深層的對象的響應式代理,即對象根屬性以及嵌套對象的屬性都是響應式的。如果使用 ES6 結構賦值,就會使得這個對象的響應式代理第一層(根屬性)屬性失去響應式,但其嵌套下的對象屬性還是響應式的。 shallowReactive 會創建淺層的對象的響應式代理,只 ...
  • 1 前言 最近有個需求,需要使用JS快速讀取外部大數據文件(60w條記錄的表)。筆者嘗試過使用JS讀取Excel文件,但是跑了十幾分鐘仍未出結果,後來筆者嘗試將原數據保存為TXT文件,再從TXT文件中讀取數據,只需幾秒鐘即可讀取完畢。在此分享一下,也留著以後備用。 2 案例 為方便快速理解,筆者挑選 ...
  • 前端常見的十種佈局方式 作為一個開發小白,也是第一次編寫博客文章,若有錯誤請各位大牛大佬指正,輕噴!!! 我在學校接觸最多的就是前端,然後最近在學習新的前端知識,發現前端佈局常見的有很多種,不同的應用場景有不同的佈局方式,下麵就來簡單介紹一下吧。 靜態佈局 浮動佈局 定位佈局 柵格佈局 table布 ...
  • 此內容包含: html基礎 列表、表格 媒體元素 表單(重點) 1、HTML 基礎 目標: 會使用HTML5的基本結構創建網頁 會使用文本相關標簽排版文本信息 會使用圖像相關標簽實現圖文並茂的頁面 會使用標簽創建超鏈接、錨鏈接及功能性鏈接 1.1、什麼是HTML HTML:Hyper Text Ma ...
  • 定義 如果希望動態給某個類添加一些屬性或者方法,但是你又不希望這個類派生的對象受到影響,那麼裝飾器模式就可以給你帶來這樣的體驗。 它的定義就是在不改變原對象的基礎上,通過對其進行包裝拓展,使得原有對象可以動態具有更多功能,從而滿足用戶的更複雜需求。 舉個例子,一部手機,你可以買各種花里胡哨的手機殼等 ...
  • MVVM M:模型(Model):data V:視圖(View):模板 VM:視圖模型(ViewModel):Vue實例對象 Vue收到了MVVM模型的啟發,MVVM是vue實現數據驅動視圖和雙向數據綁定的核心原理,通過ViewModel監聽DOM和數據源的變化。 Object.defineProp ...
  • 這篇文章主要關註分散式鎖,包括加鎖和解鎖的過程,鎖的用法,加鎖帶來的代價,對性能的影響以及如何避免死鎖。 ...
  • 1. 巨型對象 1.1. humongous object 1.2. 大於等於區域一半大小的對象 1.3. 巨型對象被直接分配在老年代,所以它在新生代回收期間不會被釋放 1.4. G1區域的大小是2的冪,最小值是1 MB 1.5. 如果堆的最大值和初始值差別很大,就會有過多的G1區域,這種情況下應該 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...