1. 方法
1.1 定義方法的完整格式
-
定義方法的完整格式:
修飾符 返回值類型 方法名稱(參數類型 參數名稱, ...) { 方法體 return 返回值; }
- 修飾符:現階段的固定寫法,public static
- 返回值類型:也就是方法最終產生的數據結果是什麼類型
- 方法名稱:方法的名字,規則和變量一樣,小駝峯
- 參數類型:進入方法的數據是什麼類型
- 參數名稱:進入方法的數據對應的變量名稱
PS:參數如果有多個,使用逗號進行分隔 - 方法體:方法需要做的事情,若干行代碼
- return:兩個作用,第一停止當前方法,第二將後面的返回值還給調用處
- 返回值:也就是方法執行後最終產生的數據結果
注意:return後面的“返回值”,必須和方法名稱前面的“返回值類型”,保持對應。
-
定義一個兩個int數字相加的方法。三要素:
- 返回值類型:int
- 方法名稱:sum
- 參數列表:int a, int b
-
方法的三種調用格式。
- 單獨調用:方法名稱(參數);
- 打印調用:System.out.println(方法名稱(參數));
- 賦值調用:數據類型 變量名稱 = 方法名稱(參數);
注意:此前學習的方法,返回值類型固定寫爲void,這種方法只能夠單獨調用,不能進行打印調用或者賦值調用。
1.2 有無參數的方法
- 有參數:小括號當中有內容,當一個方法需要一些數據條件,才能完成任務的時候,就是有參數。
例如兩個數字相加,必須知道兩個數字是各自多少,才能相加。 - 無參數:小括號當中留空。一個方法不需要任何數據條件,自己就能獨立完成任務,就是無參數。
例如定義一個方法,打印固定10次HelloWorld。
1.3 使用方法注意事項
- 方法應該定義在類當中,但是不能在方法當中再定義方法。不能嵌套。
- 方法定義的前後順序無所謂。
- 方法定義之後不會執行,如果希望執行,一定要調用:單獨調用、打印調用、賦值調用。
- 如果方法有返回值,那麼必須寫上“return 返回值;”,不能沒有。
- return後面的返回值數據,必須和方法的返回值類型,對應起來。
- 對於一個void沒有返回值的方法,不能寫return後面的返回值,只能寫return自己。
- 對於void方法當中最後一行的return可以省略不寫。
- 一個方法當中可以有多個return語句,但是必須保證同時只有一個會被執行到,兩個return不能連寫。
1.4 方法的重載
- 對於功能類似的方法來說,因爲參數列表不一樣,卻需要記住那麼多不同的方法名稱,太麻煩。
- 方法的重載(Overload):多個方法的名稱一樣,但是參數列表不一樣。
- 好處:只需要記住唯一一個方法名稱,就可以實現類似的多個功能。
- 方法重載與下列因素相關:
- 參數個數不同
- 參數類型不同
- 參數的多類型順序不同
- 方法重載與下列因素無關:
- 與參數的名稱無關
- 與方法的返回值類型無關
2. 數組
2.1 數組的概念與特點
- 數組的概念:是一種容器,可以同時存放多個數據值。
- 數組的特點:
- 數組是一種引用數據類型
- 數組當中的多個數據,類型必須統一
- 數組的長度在程序運行期間不可改變
- 數組的初始化:在內存當中創建一個數組,並且向其中賦予一些默認值。
- 兩種常見的初始化方式:
- 動態初始化(指定長度)
- 靜態初始化(指定內容)
- 動態初始化數組的格式:
數據類型[] 數組名稱 = new 數據類型[數組長度];- 解析含義:
- 左側數據類型:也就是數組當中保存的數據,全都是統一的什麼類型
- 左側的中括號:代表我是一個數組
- 左側數組名稱:給數組取一個名字
- 右側的new:代表創建數組的動作
- 右側數據類型:必須和左邊的數據類型保持一致
- 右側中括號的長度:也就是數組當中,到底可以保存多少個數據,是一個int數字
2.2 動態初始化與靜態初始化
- 動態初始化(指定長度):在創建數組的時候,直接指定數組當中的數據元素個數。
- 靜態初始化(指定內容):在創建數組的時候,不直接指定數據個數多少,而是直接將具體的數據內容進行指定。
- 靜態初始化基本格式:
- 數據類型[] 數組名稱 = new 數據類型[] { 元素1, 元素2, … };
- 注意事項:
- 雖然靜態初始化沒有直接告訴長度,但是根據大括號裏面的元素具體內容,也可以自動推算出來長度。
2.3 靜態初始化格式
- 使用靜態初始化數組的時候,格式還可以省略一下。
- 標準格式:
- 數據類型[] 數組名稱 = new 數據類型[] { 元素1, 元素2, … };
- 省略格式:
- 數據類型[] 數組名稱 = { 元素1, 元素2, … };
- 注意事項:
- 靜態初始化沒有直接指定長度,但是仍然會自動推算得到長度。
- 靜態初始化標準格式可以拆分成爲兩個步驟。
- 動態初始化也可以拆分成爲兩個步驟。
- 靜態初始化一旦使用省略格式,就不能拆分成爲兩個步驟了。
- 使用建議:
- 如果不確定數組當中的具體內容,用動態初始化;否則,已經確定了具體的內容,用靜態初始化。
2.4 數組索引
- 數組的索引編號從0開始,一直到“數組的長度-1”爲止。
- 如果訪問數組元素的時候,索引編號並不存在,那麼將會發生
數組索引越界異常
ArrayIndexOutOfBoundsException - 原因:索引編號寫錯了。
解決:修改成爲存在的正確索引編號。
3. 面向對象
面向過程:當需要實現一個功能的時候,每一個具體的步驟都要親力親爲,詳細處理每一個細節。
面向對象:當需要實現一個功能的時候,不關心具體的步驟,而是找一個已經具有該功能的人,來幫我做事兒。
3.1 new對象
- 通常情況下,一個類並不能直接使用,需要根據類創建一個對象,才能使用。
- 導包:也就是指出需要使用的類,在什麼位置。
import 包名稱.類名稱;
import cn.itcast.day06.demo01.Student;
對於和當前類屬於同一個包的情況,可以省略導包語句不寫。 - 創建,格式:
類名稱 對象名 = new 類名稱();
Student stu = new Student(); - 使用,分爲兩種情況:
使用成員變量:對象名.成員變量名
使用成員方法:對象名.成員方法名(參數)
(也就是,想用誰,就用對象名點兒誰。)
- 注意事項:
- 如果成員變量沒有進行賦值,那麼將會有一個默認值,規則和數組一樣。
3.2 局部變量和成員變量
-
定義的位置不一樣【重點】
局部變量:在方法的內部
成員變量:在方法的外部,直接寫在類當中 -
作用範圍不一樣【重點】
局部變量:只有方法當中纔可以使用,出了方法就不能再用
成員變量:整個類全都可以通用。 -
默認值不一樣【重點】
局部變量:沒有默認值,如果要想使用,必須手動進行賦值
成員變量:如果沒有賦值,會有默認值,規則和數組一樣 -
內存的位置不一樣(瞭解)
局部變量:位於棧內存
成員變量:位於堆內存 -
生命週期不一樣(瞭解)
局部變量:隨着方法進棧而誕生,隨着方法出棧而消失
成員變量:隨着對象創建而誕生,隨着對象被垃圾回收而消失
3.3 面向對象三大特徵
- 面向對象三大特徵:封裝、繼承、多態
- 封裝性在Java當中的體現:
- 方法就是一種封裝
- 關鍵字private也是一種封裝
- 封裝就是將一些細節信息隱藏起來,對於外界不可見。
3.4 封裝
- 問題描述:定義Person的年齡時,無法阻止不合理的數值被設置進來。
- 解決方案:用private關鍵字將需要保護的成員變量進行修飾。
- 一旦使用了private進行修飾,那麼本類當中仍然可以隨意訪問。
但是!超出了本類範圍之外就不能再直接訪問了。 - 間接訪問private成員變量,就是定義一對兒Getter/Setter方法
- 必須叫setXxx或者是getXxx命名規則。
- 對於Getter來說,不能有參數,返回值類型和成員變量對應;
- 對於Setter來說,不能有返回值,參數類型和成員變量對應。
3.5 構造方法
- 構造方法是專門用來創建對象的方法,當我們通過關鍵字new來創建對象時,其實就是在調用構造方法。
- 格式:
public 類名稱(參數類型 參數名稱) { 方法體 }
- 注意事項:
- 構造方法的名稱必須和所在的類名稱完全一樣,就連大小寫也要一樣
- 構造方法不要寫返回值類型,連void都不寫
- 構造方法不能return一個具體的返回值
- 如果沒有編寫任何構造方法,那麼編譯器將會默認贈送一個構造方法,沒有參數、方法體什麼事情都不做。
public Student() {} - 一旦編寫了至少一個構造方法,那麼編譯器將不再贈送。
- 構造方法也是可以進行重載的。
重載:方法名稱相同,參數列表不同。
3.6 Java Bean
- 一個標準的類通常要擁有下面四個組成部分:
- 所有的成員變量都要使用private關鍵字修飾
- 爲每一個成員變量編寫一對兒Getter/Setter方法
- 編寫一個無參數的構造方法
- 編寫一個全參數的構造方法
- 這樣標準的類也叫做Java Bean
4. Scanner類
- Scanner類的功能:可以實現鍵盤輸入數據,到程序當中。
- 引用類型的一般使用步驟:
- 導包
import 包路徑.類名稱;
如果需要使用的目標類,和當前類位於同一個包下,則可以省略導包語句不寫。
只有java.lang包下的內容不需要導包,其他的包都需要import語句。 - 創建
類名稱 對象名 = new 類名稱(); - 使用
對象名.成員方法名()
- 導包
- 獲取鍵盤輸入的一個int數字:int num = sc.nextInt();
- 獲取鍵盤輸入的一個字符串:String str = sc.next();
4.1 new對象格式
- 創建對象的標準格式:
- 類名稱 對象名 = new 類名稱();
- 匿名對象就是隻有右邊的對象,沒有左邊的名字和賦值運算符。
- new 類名稱();
- 注意事項:匿名對象只能使用唯一的一次,下次再用不得不再創建一個新對象。
- 使用建議:如果確定有一個對象只需要使用唯一的一次,就可以用匿名對象。
5. Random類
- Random類用來生成隨機數字。使用起來也是三個步驟:
- 導包
import java.util.Random; - 創建
Random r = new Random(); // 小括號當中留空即可 - 使用
獲取一個隨機的int數字(範圍是int所有範圍,有正負兩種):int num = r.nextInt()
獲取一個隨機的int數字(參數代表了範圍,左閉右開區間):int num = r.nextInt(3)
實際上代表的含義是:[0,3),也就是0~2
6. 數組與集合的區別
- 數組的長度不可以發生改變。
- 但是ArrayList集合的長度是可以隨意變化的。
- 對於ArrayList來說,有一個尖括號代表泛型。
- 泛型:也就是裝在集合當中的所有元素,全都是統一的什麼類型。
- 注意:泛型只能是引用類型,不能是基本類型。
- 注意事項:
- 對於ArrayList集合來說,直接打印得到的不是地址值,而是內容。
- 如果內容是空,得到的是空的中括號:[]
7. 包裝類
- 如果希望向集合ArrayList當中存儲基本類型數據,必須使用基本類型對應的“包裝類”。
基本類型 包裝類(引用類型,包裝類都位於java.lang包下) byte Byte short Short int Integer 【特殊】 long Long float Float double Double char Character 【特殊】 boolean Boolean - 從JDK 1.5+開始,支持自動裝箱、自動拆箱。
- 自動裝箱:基本類型 --> 包裝類型
- 自動拆箱:包裝類型 --> 基本類型
8. String類
java.lang.String類代表字符串。
API當中說:Java 程序中的所有字符串字面值(如 “abc” )都作爲此類的實例實現。
其實就是說:程序當中所有的雙引號字符串,都是String類的對象。(就算沒有new,也照樣是。)
- 字符串的特點:
- 字符串的內容永不可變。【重點】
- 正是因爲字符串不可改變,所以字符串是可以共享使用的。
- 字符串效果上相當於是char[]字符數組,但是底層原理是byte[]字節數組。
創建字符串的常見3+1種方式。
- 三種構造方法:
- public String():創建一個空白字符串,不含有任何內容。
- public String(char[] array):根據字符數組的內容,來創建對應的字符串。
- public String(byte[] array):根據字節數組的內容,來創建對應的字符串。
- 一種直接創建:
- String str = “Hello”; // 右邊直接用雙引號
注意:直接寫上雙引號,就是字符串對象。
- String str = “Hello”; // 右邊直接用雙引號
8.1 String類方法使用
- public int length():獲取字符串當中含有的字符個數,拿到字符串長度。
- public String concat(String str):將當前字符串和參數字符串拼接成爲返回值新的字符串。
- public char charAt(int index):獲取指定索引位置的單個字符。(索引從0開始。)
- public int indexOf(String str):查找參數字符串在本字符串當中首次出現的索引位置,如果沒有返回-1值。
- public String substring(int index):截取從參數位置一直到字符串末尾,返回新字符串。
- public String substring(int begin, int end):截取從begin開始,一直到end結束,中間的字符串。
備註:[begin,end),包含左邊,不包含右邊。
- public char[] toCharArray():將當前字符串拆分成爲字符數組作爲返回值。
- public byte[] getBytes():獲得當前字符串底層的字節數組。
- public String replace(CharSequence oldString, CharSequence newString):
將所有出現的老字符串替換成爲新的字符串,返回替換之後的結果新字符串。
備註:CharSequence意思就是說可以接受字符串類型。
- public String[] split(String regex):按照參數的規則,將字符串切分成爲若干部分。
注意事項:
split方法的參數其實是一個“正則表達式”,今後學習。
今天要注意:如果按照英文句點“.”進行切分,必須寫"\\."(兩個反斜槓)
9. static關鍵字
如果一個成員變量使用了static關鍵字,那麼這個變量不再屬於對象自己,而是屬於所在的類。多個對象共享同一份數據。
9.1 static關鍵字注意事項
- 一旦使用static修飾成員方法,那麼這就成爲了靜態方法。靜態方法不屬於對象,而是屬於類的。
- 如果沒有static關鍵字,那麼必須首先創建對象,然後通過對象才能使用它。
- 如果有了static關鍵字,那麼不需要創建對象,直接就能通過類名稱來使用它。
- 無論是成員變量,還是成員方法。如果有了static,都推薦使用類名稱進行調用。
- 靜態變量:類名稱.靜態變量
- 靜態方法:類名稱.靜態方法()
- 注意事項:
- 靜態不能直接訪問非靜態。
原因:因爲在內存當中是【先】有的靜態內容,【後】有的非靜態內容。
“先人不知道後人,但是後人知道先人。” - 靜態方法當中不能用this。
原因:this代表當前對象,通過誰調用的方法,誰就是當前對象。
- 靜態不能直接訪問非靜態。
9.2 靜態代碼塊
- 靜態代碼塊的格式是:
public class 類名稱 { static { // 靜態代碼塊的內容 } }
- 特點:當第一次用到本類時,靜態代碼塊執行唯一的一次。
靜態內容總是優先於非靜態,所以靜態代碼塊比構造方法先執行。 - 靜態代碼塊的典型用途:
用來一次性地對靜態成員變量進行賦值。
10. Math類
- java.util.Math類是數學相關的工具類,裏面提供了大量的靜態方法,完成與數學運算相關的操作。
public static double abs(double num):獲取絕對值。有多種重載。
public static double ceil(double num):向上取整。
public static double floor(double num):向下取整。
public static long round(double num):四捨五入。
- Math.PI代表近似的圓周率常量(double)。
11. 繼承
- 在繼承的關係中,“子類就是一個父類”。也就是說,子類可以被當做父類看待。
- 例如父類是員工,子類是講師,那麼“講師就是一個員工”。關係:is-a。
- 定義父類的格式:(一個普通的類定義)
public class 父類名稱 { // ... }
- 定義子類的格式:
public class 子類名稱 extends 父類名稱 { // ... }
11.1 繼承訪問成員變量
- 在父子類的繼承關係當中,如果成員變量重名,則創建子類對象時,訪問有兩種方式:
- 直接通過子類對象訪問成員變量:
- 等號左邊是誰,就優先用誰,沒有則向上找。
- 間接通過成員方法訪問成員變量:
- 該方法屬於誰,就優先用誰,沒有則向上找。
- 直接通過子類對象訪問成員變量:
11.2 繼承中變量的訪問
- 局部變量: 直接寫成員變量名
- 本類的成員變量: this.成員變量名
- 父類的成員變量: super.成員變量名
11.3 繼承中方法重寫
- 在父子類的繼承關係當中,創建子類對象,訪問成員方法的規則:
- 創建的對象是誰,就優先用誰,如果沒有則向上找。
- 注意事項:
- 無論是成員方法還是成員變量,如果沒有都是向上找父類,絕對不會向下找子類的。
- 重寫(Override)
- 概念:在繼承關係當中,方法的名稱一樣,參數列表也一樣。
- 重寫(Override):方法的名稱一樣,參數列表【也一樣】。覆蓋、覆寫。
- 方法的覆蓋重寫特點:創建的是子類對象,則優先用子類方法。
- 重載(Overload):方法的名稱一樣,參數列表【不一樣】。
11.4 方法覆蓋重寫的注意事項
- 必須保證父子類之間方法的名稱相同,參數列表也相同。
- @Override:寫在方法前面,用來檢測是不是有效的正確覆蓋重寫。
- 這個註解就算不寫,只要滿足要求,也是正確的方法覆蓋重寫。
- 子類方法的返回值必須【小於等於】父類方法的返回值範圍。
- 小擴展提示:java.lang.Object類是所有類的公共最高父類(祖宗類),java.lang.String就是Object的子類。
- 子類方法的權限必須【大於等於】父類方法的權限修飾符。
- 小擴展提示:public > protected > (default) > private
- 備註:(default)不是關鍵字default,而是什麼都不寫,留空。
11.5 繼承中構造方法訪問
- 繼承關係中,父子類構造方法的訪問特點:
- 子類構造方法當中有一個默認隱含的“super()”調用,所以一定是先調用的父類構造,後執行的子類構造。
- 子類構造可以通過super關鍵字來調用父類重載構造。
- super的父類構造調用,必須是子類構造方法的第一個語句。不能一個子類構造調用多次super構造。
- 總結:
- 子類必須調用父類構造方法,不寫則贈送super();
- 寫了則用寫的指定的super調用,super只能有一個,還必須是第一個。
12. 抽象
- 抽象方法:就是加上abstract關鍵字,然後去掉大括號,直接分號結束。
- 抽象類:抽象方法所在的類,必須是抽象類才行。在class之前寫上abstract即可。
- 如何使用抽象類和抽象方法:
- 不能直接創建new抽象類對象。
- 必須用一個子類來繼承抽象父類。
- 子類必須覆蓋重寫抽象父類當中所有的抽象方法。
覆蓋重寫(實現):子類去掉抽象方法的abstract關鍵字,然後補上方法體大括號。 - 創建子類對象進行使用。
13. 接口
- 接口就是多個類的公共規範。
- 接口是一種引用數據類型,最重要的內容就是其中的:抽象方法。
- 如何定義一個接口的格式:
public interface 接口名稱 { // 接口內容 }
- 備註:換成了關鍵字interface之後,編譯生成的字節碼文件仍然是:.java --> .class。
- 如果是Java 7,那麼接口中可以包含的內容有:
- 常量
- 抽象方法
- 如果是Java 8,還可以額外包含有:
3. 默認方法
4. 靜態方法 - 如果是Java 9,還可以額外包含有:
5. 私有方法 - 接口使用步驟:
- 接口不能直接使用,必須有一個“實現類”來“實現”該接口。
格式:public class 實現類名稱 implements 接口名稱 { // ... }
- 接口的實現類必須覆蓋重寫(實現)接口中所有的抽象方法。
實現:去掉abstract關鍵字,加上方法體大括號。 - 創建實現類的對象,進行使用。
- 接口不能直接使用,必須有一個“實現類”來“實現”該接口。
- 注意事項:
- 如果實現類並沒有覆蓋重寫接口中所有的抽象方法,那麼這個實現類自己就必須是抽象類。
13.1 接口實現重點
- 接口的默認方法,可以通過接口實現類對象,直接調用。
- 接口的默認方法,也可以被接口實現類進行覆蓋重寫。
13.2 接口中靜態方法的調用
- 注意事項:不能通過接口實現類的對象來調用接口當中的靜態方法。
- 正確用法:通過接口名稱,直接調用其中的靜態方法。
- 格式:
- 接口名稱.靜態方法名(參數);
13.3 接口中定義抽象方法
- 在任何版本的Java中,接口都能定義抽象方法。
- 格式:
public abstract 返回值類型 方法名稱(參數列表); - 注意事項:
- 接口當中的抽象方法,修飾符必須是兩個固定的關鍵字:public abstract
- 這兩個關鍵字修飾符,可以選擇性地省略。(今天剛學,所以不推薦。)
- 方法的三要素,可以隨意定義。
13.4 接口中的常量
- 接口當中也可以定義“成員變量”,但是必須使用public static final三個關鍵字進行修飾。
- 從效果上看,這其實就是接口的【常量】。
- 格式:
public static final 數據類型 常量名稱 = 數據值; - 備註:
一旦使用final關鍵字進行修飾,說明不可改變。 - 注意事項:
- 接口當中的常量,可以省略public static final,注意:不寫也照樣是這樣。
- 接口當中的常量,必須進行賦值;不能不賦值。
- 接口中常量的名稱,使用完全大寫的字母,用下劃線進行分隔。(推薦命名規則)
13.5 接口定義默認方法
- 從Java 8開始,接口裏允許定義默認方法。
- 格式
public default 返回值類型 方法名稱(參數列表) { 方法體 }
- 備註:接口當中的默認方法,可以解決接口升級的問題。
- 【私有方法】
- 問題描述:
- 我們需要抽取一個共有方法,用來解決兩個默認方法之間重複代碼的問題。
- 但是這個共有方法不應該讓實現類使用,應該是私有化的。
- 解決方案:
- 從Java 9開始,接口當中允許定義私有方法。
- 普通私有方法,解決多個默認方法之間重複代碼問題
- 格式
private 返回值類型 方法名稱(參數列表) { 方法體 }
- 靜態私有方法,解決多個靜態方法之間重複代碼問題
- 格式:
private static 返回值類型 方法名稱(參數列表) { 方法體 }
- 問題描述:
13.6 接口定義靜態方法
- 從Java 8開始,接口當中允許定義靜態方法。
- 格式:
public static 返回值類型 方法名稱(參數列表) { 方法體 }
- 提示:就是將abstract或者default換成static即可,帶上方法體。
13.7 接口使用注意事項
- 接口是沒有靜態代碼塊或者構造方法的。
- 一個類的直接父類是唯一的,但是一個類可以同時實現多個接口。
- 格式:
public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB { // 覆蓋重寫所有抽象方法 }
- 如果實現類所實現的多個接口當中,存在重複的抽象方法,那麼只需要覆蓋重寫一次即可。
- 如果實現類沒有覆蓋重寫所有接口當中的所有抽象方法,那麼實現類就必須是一個抽象類。
- 如果實現類鎖實現的多個接口當中,存在重複的默認方法,那麼實現類一定要對衝突的默認方法進行覆蓋重寫。
- 一個類如果直接父類當中的方法,和接口當中的默認方法產生了衝突,優先用父類當中的方法。
13.8 類與接口的關係
- 類與類之間是單繼承的。直接父類只有一個。
- 類與接口之間是多實現的。一個類可以實現多個接口。
- 接口與接口之間是多繼承的。
- 注意事項:
- 多個父接口當中的抽象方法如果重複,沒關係。
- 多個父接口當中的默認方法如果重複,那麼子接口必須進行默認方法的覆蓋重寫,【而且帶着default關鍵字】。
14. 多態
- 代碼當中體現多態性,其實就是一句話:父類引用指向子類對象。
- 格式:
父類名稱 對象名 = new 子類名稱();
或者:
接口名稱 對象名 = new 實現類名稱();
14.1 多態訪問
- 在多態的代碼當中,成員方法的訪問規則是:
- 看new的是誰,就優先用誰,沒有則向上找。
- 口訣:編譯看左邊,運行看右邊。
- 對比一下:
- 成員變量:編譯看左邊,運行還看左邊。
- 成員方法:編譯看左邊,運行看右邊。
14.2 向上向下轉型
- 向上轉型一定是安全的,沒有問題的,正確的。但是也有一個弊端:
- 對象一旦向上轉型爲父類,那麼就無法調用子類原本特有的內容。
- 解決方案:用對象的向下轉型【還原】。
15. final關鍵字
- final關鍵字代表最終、不可改變的。
- 常見四種用法:
- 可以用來修飾一個類
- 可以用來修飾一個方法
- 還可以用來修飾一個局部變量
- 還可以用來修飾一個成員變量
15.1 final修飾方法
- 當final關鍵字用來修飾一個方法的時候,這個方法就是最終方法,也就是不能被覆蓋重寫。
- 格式:
修飾符 final 返回值類型 方法名稱(參數列表) { // 方法體 }
- 注意事項:
- 對於類、方法來說,abstract關鍵字和final關鍵字不能同時使用,因爲矛盾。
15.2 final修飾類
- 當final關鍵字用來修飾一個類的時候,格式:
public final class 類名稱 { // ... }
- 含義:當前這個類不能有任何的子類。(太監類)
- 注意:一個類如果是final的,那麼其中所有的成員方法都無法進行覆蓋重寫(因爲沒兒子。)
15.3 final修飾成員變量
- 對於成員變量來說,如果使用final關鍵字修飾,那麼這個變量也照樣是不可變。
- 由於成員變量具有默認值,所以用了final之後必須手動賦值,不會再給默認值了。
- 對於final的成員變量,要麼使用直接賦值,要麼通過構造方法賦值。二者選其一。
- 必須保證類當中所有重載的構造方法,都最終會對final的成員變量進行賦值。
16. Java中有四種權限修飾符
範圍 | public | protected | (default) | private |
---|---|---|---|---|
同一個類(我自己) | YES | YES | YES | YES |
同一個包(我鄰居) | YES | YES | YES | NO |
不同包子類(我兒子) | YES | YES | NO | NO |
不同包非子類(陌生人) | YES | NO | NO | NO |
注意事項:(default)並不是關鍵字“default”,而是根本不寫。
17. 內部類
- 如果一個事物的內部包含另一個事物,那麼這就是一個類內部包含另一個類。
- 例如:身體和心臟的關係。又如:汽車和發動機的關係。
- 分類:
- 成員內部類
- 局部內部類(包含匿名內部類)
- 成員內部類的定義格式:
修飾符 class 外部類名稱 { 修飾符 class 內部類名稱 { // ... } // ... }
注意:內用外,隨意訪問;外用內,需要內部類對象。
17.1 成員內部類
- 如何使用成員內部類?有兩種方式:
- 間接方式:在外部類的方法當中,使用內部類;然後main只是調用外部類的方法。
- 直接方式,公式:
類名稱 對象名 = new 類名稱();
【外部類名稱.內部類名稱 對象名 = new 外部類名稱().new 內部類名稱();】
17.2 局部內部類1
- 局部內部類,如果希望訪問所在方法的局部變量,那麼這個局部變量必須是【有效final的】。
- 備註:從Java 8+開始,只要局部變量事實不變,那麼final關鍵字可以省略。
- 原因:
- new出來的對象在堆內存當中。
- 局部變量是跟着方法走的,在棧內存當中。
- 方法運行結束之後,立刻出棧,局部變量就會立刻消失。
- 但是new出來的對象會在堆當中持續存在,直到垃圾回收消失。
17.3 局部內部類2
- 如果一個類是定義在一個方法內部的,那麼這就是一個局部內部類。
- “局部”:只有當前所屬的方法才能使用它,出了這個方法外面就不能用了。
- 定義格式:
修飾符 class 外部類名稱 { 修飾符 返回值類型 外部類方法名稱(參數列表) { class 局部內部類名稱 { // ... } } }
17.4 類的權限修飾符
- public > protected > (default) > private
- 定義一個類的時候,權限修飾符規則:
- 外部類:public / (default)
- 成員內部類:public / protected / (default) / private
- 局部內部類:什麼都不能寫
17.5 匿名內部類
- 如果接口的實現類(或者是父類的子類)只需要使用唯一的一次,
那麼這種情況下就可以省略掉該類的定義,而改爲使用【匿名內部類】。 - 匿名內部類的定義格式:
接口名稱 對象名 = new 接口名稱() { // 覆蓋重寫所有抽象方法 };
- 對格式“new 接口名稱() {…}”進行解析:
- new代表創建對象的動作
- 接口名稱就是匿名內部類需要實現哪個接口
- {…}這纔是匿名內部類的內容
- 另外還要注意幾點問題:
- 匿名內部類,在【創建對象】的時候,只能使用唯一一次。
如果希望多次創建對象,而且類的內容一樣的話,那麼就需要使用單獨定義的實現類了。 - 匿名對象,在【調用方法】的時候,只能調用唯一一次。
如果希望同一個對象,調用多次方法,那麼必須給對象起個名字。 - 匿名內部類是省略了【實現類/子類名稱】,但是匿名對象是省略了【對象名稱】
強調:匿名內部類和匿名對象不是一回事!!!
- 匿名內部類,在【創建對象】的時候,只能使用唯一一次。