Java剑开天门(二)
Java知識復習二
相關導航
Java劍開天門(一)
Java劍開天門(二)
Java劍開天門(三)
Java劍開天門(四)
Java劍開天門(五)
Java導航
- Java知識復習二
- 前言
- 一、數組與方法
- 1.1 數組定義
- 1.2 數組初始化
- 1.3 方法定義
- 1.4 方法重載(OverLoading)
- 1.4.1 定義
- 1.4.2 規則
- 1.5 方法重寫(`@Override`注解)
- 1.5.1 定義
- 1.5.2 規則
- 1.6 重寫與重載關系
- 1.7 方法引用
- 1.7.1 定義
- 二、數組常用方法
- 1、打印數組
- 2、數組排序
- 3、數組長度
- 4、數組相等
- 5、數組克隆
- 6、合并數組
- 7、反轉數組
- 8、移除元素
- 9、將數組元素組成一個字符串
- 10、檢查數組是否包含某一個值
- 11、ArrayList集合與Array數組相互轉化
- 三、面向對象程序設計
- 1、面向對象三大特性
- 1.1 封裝
- 1.2 繼承
- 1.3 多態
- 2、類和對象基礎知識
- 2.1 類的定義
- 2.2 對象的創建及使用
- 2.3 構造方法
- 2.4 內部類
- 3、 幾個關鍵字
- 3.1 this關鍵字
- 1)this.屬性名
- 2)this.方法
- 3)this.()
- 3.2 super關鍵字
- 1)super()
- 2)super.屬性名/方法
- 3)super關鍵字和this關鍵字重要結論
- 3.3 instanceof關鍵字
- 4、抽象類和接口
- 4.1 抽象類
- 1)抽象方法
- 2)抽象類
- 4.2 接口
- 4.3 抽象類和接口的區別
- 1)語法層面
- 2)設計層面
前言
本博文重在夯實Java基礎的知識點,回歸書本,夯實基礎,學深學精
近期需要鞏固項目和找實習,計劃打算將Java基礎從頭復習一遍,夯實基礎,可能對Java的一些機制不了解或者一知半解,正好借此機會深入學習,也算記錄自己的一個學習總結。
Java基礎參考書籍:《Java 開發實戰經典 名師講壇 第2版》與《Java核心技術 卷I》
一、數組與方法
#mermaid-svg-rqsOhCXt1U1KwnIA {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-rqsOhCXt1U1KwnIA .error-icon{fill:#552222;}#mermaid-svg-rqsOhCXt1U1KwnIA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rqsOhCXt1U1KwnIA .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-rqsOhCXt1U1KwnIA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rqsOhCXt1U1KwnIA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rqsOhCXt1U1KwnIA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rqsOhCXt1U1KwnIA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rqsOhCXt1U1KwnIA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rqsOhCXt1U1KwnIA .marker.cross{stroke:#333333;}#mermaid-svg-rqsOhCXt1U1KwnIA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rqsOhCXt1U1KwnIA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rqsOhCXt1U1KwnIA .cluster-label text{fill:#333;}#mermaid-svg-rqsOhCXt1U1KwnIA .cluster-label span{color:#333;}#mermaid-svg-rqsOhCXt1U1KwnIA .label text,#mermaid-svg-rqsOhCXt1U1KwnIA span{fill:#333;color:#333;}#mermaid-svg-rqsOhCXt1U1KwnIA .node rect,#mermaid-svg-rqsOhCXt1U1KwnIA .node circle,#mermaid-svg-rqsOhCXt1U1KwnIA .node ellipse,#mermaid-svg-rqsOhCXt1U1KwnIA .node polygon,#mermaid-svg-rqsOhCXt1U1KwnIA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rqsOhCXt1U1KwnIA .node .label{text-align:center;}#mermaid-svg-rqsOhCXt1U1KwnIA .node.clickable{cursor:pointer;}#mermaid-svg-rqsOhCXt1U1KwnIA .arrowheadPath{fill:#333333;}#mermaid-svg-rqsOhCXt1U1KwnIA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rqsOhCXt1U1KwnIA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rqsOhCXt1U1KwnIA .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-rqsOhCXt1U1KwnIA .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-rqsOhCXt1U1KwnIA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rqsOhCXt1U1KwnIA .cluster text{fill:#333;}#mermaid-svg-rqsOhCXt1U1KwnIA .cluster span{color:#333;}#mermaid-svg-rqsOhCXt1U1KwnIA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rqsOhCXt1U1KwnIA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Java數組 數組分類 方法定義 數組方法 一維數組 二維數組 多維數組 定義格式 方法重載 方法重寫 方法引用 打印數組 數組排序 數組長度 數組相等 數組克隆 合并數組 反轉數組 移除元素 將數組元素組成一個字符串 檢查數組是否包含某一個值 ArrayList集合與Array數組相互轉化1.1 數組定義
- 是一個線性的序列,一組數據的集合,可以快速訪問其他的元素。
- 當創建了一個數組時,他的容量是不變的,而且在生命周期也是不能改變的。
- JAVA數組會做邊界檢查,如果發現有越界現象,會報RuntimeException異常錯誤,當然檢查邊界會以效率為代價。
- JAVA還提供其他集合,list,map,set,他們處理對象的時候就好像這些對象沒有自己的類型一樣,而是直接歸根于Object,這樣只需要創建一個集合,把對象放進去,取出時轉換成自己的類型就行了。
數組是特殊的集合,是線性的集合,集合和數組的區別如下
?1) 數組聲明了它容納的元素的類型,而集合可以不聲明。
?2) 數組是靜態的,一個數組實例具有固定的大小,一旦創建了就無法改變容量了。而集合是可以動態擴展容量,可以根據需要動態改變大小,集合提供更多的成員方法,能滿足更多的需求。
?3) 數組的存放的類型只能是一種(基本類型/引用類型),集合存放的類型可以不是一種(不加泛型時添加的類型是Object)。
?4) 數組是Java語言中內置的數據類型,是線性排列的,執行效率或者類型檢查都是最快的。 - 集合體系結構
1.2 數組初始化
數組的索引從0開始,側重學習一維數組
- 一維數組
- 二維數組
?如果把一維數組比作幾何圖形中的線性圖形,那么二維數組就相當于一個表格
?左索引代表行,右索引代表列
- 多維數組
?只需在聲明數組時將索引與中括號再加一組就可提高數組的維數。
?如三維數組? 數據類型 ?[][][] ?數組名稱=new? 數據類型 ?[個數][個數][個數] ;
1.3 方法定義
- 解決某件事的功能實現。
- 是一段代碼塊的封裝,是某一功能的實現。
? 語法格式
- 修飾符
這是可選的,告訴編譯器如何調用該方法,定義了該方法的訪問類型。
? 訪問控制權限修飾符
? 訪問控制權限修飾符來控制元素的訪問范圍。
? ? public ? 表示公開的,在任何位置都可以訪問。
? ? protected ? 同包、子類(繼承)可以訪問
? ? 缺省 ? 表示default權限的,同包下可以訪問。
? ? private ? 表示私有的,只能在本類中可以訪問。
? ? 修飾符的范圍: private < 缺省 < protected < public
? ? 訪問控制權限修飾符可以修飾:類、變量、方法…
? 非訪問控制權限修飾符
? Java非訪問控制修飾符包括: final, abstract, static,synchronized 和 volatile。
? ? final ? 表示最終的,不可被改變的, 用于修飾類、方法、屬性和變量
? ? ? ? 1) 用final修飾類時,被修飾的類不可以被繼承。final類中的所有成員方法都會被隱式地指定為final方法。
? ? ? ? 2)用final修飾方法時,被修飾的方法不能被重寫。在早期的Java版本中被final修飾的方法會轉為內嵌調用從而提升性能。(注:類的private方法會隱式地被指定為final方法。)
? ? ? ? 3)用fina修飾的變量,如果是基本數據類型的變量,則其數值一旦在初始化之后便不能更改;如果是引用類型的變量,則在對其初始化之后便不能再讓其指向另一個對象。(注:用fianl修飾的類屬性變量必須進行初始化(包括在構造方法中初始化))
? ? static? 靜態的,全局的,用于修飾類、方法、變量和代碼塊
? ? static對象可以在它的任何對象創建之前訪問,無需引用任何對象,可以通過類名加“.”進行直接訪問。
? ? ? ? 1) 如果一個類要被聲明為static的,只有一種情況,就是靜態內部類。靜態內部類可以聲明普通成員變量和方法,而普通內部類不能聲明static成員變量和方法。
? ? ? ? 2)用static修飾的代碼塊也叫靜態代碼塊,是在類中獨立于類成員的static語句塊,它不在任何的方法體內,可以有多個,位置可以隨便放,JVM加載類時會執行這些靜態的代碼塊,如果static代碼塊有多個,JVM將按照它們在類中出現的先后順序依次執行它們,每個代碼塊只會被執行一次。
? ? ? ? 3)用static修飾的方法,只能調用static變量和static方法,不能以任何形式引用this和super,是抽象方法abstract。
? ? ? ? 4)用static修飾的變量,在定義時必須要進行初始化,且初始化時間要早于非靜態變量。
? ? native? 原生的,本地的? 用于修飾方法
? ? native關鍵字用來修飾方法。被native關鍵字修飾的方法是一個原生態方法,方法對應的實現不是在當前文件,而是在用其他語言(如C和C++)實現的文件中。Java使用native方法來擴展Java程序的功能,通過JNI接口調用其他語言來實現對底層的訪問。
? ? volatile? 易變的,不穩定的,用于修飾變量
? ? 用 volatile 修飾的變量通常是為了保證不同線程對這個變量進行操作時的可見性,即一個線程修改了某個變量的值,這新值對其他線程來說是立即可見的。volatile是Java提供的一種輕量級的同步機制,在并發編程中,它也扮演著比較重要的角色,可以被看作是一種 “程度較輕的 synchronized ”。與 synchronized 塊相比,volatile 變量所需的編碼較少,并且運行時開銷也較少,但是它所能實現的功能也僅是 synchronized 的一部分。
? ? ? ? 1) 當一個共享變量被 volatile 修飾時,它會保證修改的值會立即被更新到主存,當有其他線程需要讀取時,它會去主存中讀取新值。也就是每次取值在都會取內存中的值,每次更新都會立即更新主存中的值。
? ? ? ? 2) volatile 關鍵字能禁止指令重排序,所以 volatile 能在一定程度上保證有序性。volatile 關鍵字禁止指令重排序有兩層意思,
? ? ? ? ?①當程序執行到 volatile 變量的讀操作或者寫操作時,在其前面的操作的更改肯定全部已經進行,且結果已經對后面的操作可見,在其后面的操作肯定還沒有進行;
? ? ? ? ?②在進行指令優化時,不能將在對 volatile 變量訪問的語句放在其后面執行,也不能把 volatile 變量后面的語句放到其前面執行。
? ? synchronized? 同步,在時間上一致,同步進行,用于修飾方法和代碼塊。
? ? 用 synchronized 修飾方法和代碼塊來控制在同一時刻只有一個線程執行該段代碼,從而保證多并發情況下的數據安全。synchronized 就是給修飾的方法或代碼塊聲明一個鎖。用synchronized 修飾方法和代碼塊通常被稱為“加鎖”。
? ? ? ? 1) 類鎖:簡單來說,線程執行到一個類鎖,其它被synchronized修飾的此類鎖不能被執行。 當 synchronized 修飾靜態方法或 synchronized 修飾代碼塊時傳入某個class對象(synchronized (XXXX.class))時被稱為類鎖。某個線程得到了一個類鎖之后,其他所有被該類鎖加鎖方法或代碼塊是鎖定的, 其他線程是無法訪問的,但是其他線程還是可以訪問沒有被該類鎖加鎖的任何代碼。
? ? ? ? 2)對象鎖:簡單來說,線程執行到一個對象鎖,其它被synchronized修飾的此對象鎖不能被執行。 當 synchronized 修飾非靜態方法或 synchronized 修飾代碼塊時傳入非class對象(synchronized this))時被稱為對象鎖。某個線程得到了對象鎖之后,該對象的其他被 synchronized修飾的方法(同步方法)是鎖定的,其他線程是無法訪問的。但是其他線程還是可以訪問沒有進行同步的方法或者代碼;當獲取到與對象關聯的內置鎖時,并不能阻止其他線程訪問該對象,當某個線程獲得對象的鎖之后,只能阻止其他線程獲得同一個鎖。
? ? ? ? 3)區別與關系: 如同每個類只有一個class對象而類的實例可以有很多個一樣,每個類只有一個類鎖,每個實例都有自己的對象鎖,所以不同對象實例的對象鎖是互不干擾的。但是有一點必須注意的是,其實類鎖只是一個概念上的東西,并不是真實存在的,它只是用來幫助我們理解鎖定實例方法和靜態方法的區別的。類鎖和對象鎖是不一樣的鎖,是互相獨立的,兩者不存在競爭關系,線程獲得對象鎖的同時,也可以獲得該類鎖,即同時獲得兩個鎖,這是允許的。
? ? ? ? 4) 因為被 synchronized 修飾的代碼在同一時刻只有一個線程執行,所以也就保證了操作的原子性和內存可見性。
- 返回值類型
方法可能有返回值。返回值無則用void,有返回值則用對應的返回數據類型。
一般用一個變量來接住返回值,在最后return這個變量。 - 方法名
方法的實際名稱,方法名和參數表共同構成方法簽名。 - 參數類型
參數像一個占位符。
當方法被調用時,傳遞值給參數,這個值被稱為實參或者變量。
參數表是指方法的參數類型、順序、和參數的個數。參數是可選的,方法可以不包含任何參數。
形式參數:在方法被調用時用于接收外界輸入的數據。即定義方法時的參數。
實參:調用方法時實際傳給方法的數據。是調用方法時的參數。
1.4 方法重載(OverLoading)
1.4.1 定義
??方法重載是指在一個類中定義多個同名的方法,但要求每個方法具有不同的參數的類型或參數的個數。
??Java的方法重載,就是在類中可以創建多個方法,它們可以有相同的名字,但必須具有不同的參數,即或者是參數的個數不同,或者是參數的類型不同。
??調用方法時通過傳遞給它們的不同個數和類型的參數,以及傳入參數的順序來決定具體使用哪個方法。
發生在同一個類中
方法重載就是方法名稱重復,參數列表不同即加載參數不同,方法體可不同
1.4.2 規則
-
被重載的方法必須改變參數列表;
-
被重載的方法可以改變返回類型;
-
被重載的方法可以改變訪問修飾符;
-
被重載的方法可以聲明新的或更廣的檢查異常;
-
方法能夠在同一個類中或者在一個子類中被重載。
1.5 方法重寫(@Override注解)
1.5.1 定義
??在Java和其他一些高級面向對象的編程語言中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。
??但有時子類并不想原封不動地繼承父類的方法,而是想作一定的修改,這就需要采用方法的重寫。方法重寫又稱方法覆蓋。
發生在不同類中
方法重寫就是方法名、參數列表、返回值相同,方法體不同
1.5.2 規則
-
方法名、參數、返回值相同;
-
子類方法不能縮小父類方法的訪問權限;
-
子類方法不能拋出比父類方法更多的異常(但子類方法可以不拋出異常);
-
存在于父類和子類之間;
-
方法被定義為final不能被重寫。
1.6 重寫與重載關系
??重載(overload)和覆蓋(overide)是 Java 多態性的不同表現方式。
1.7 方法引用
1.7.1 定義
??當要傳遞給Lambda體的操作,已經有了實現方法,可以使用方法引用。
??方法引用涉及到Lambda表達式,會在Lambda這一章節具體學習。
二、數組常用方法
Java8中文API
1、打印數組
import java.util.Arrays;//導包 static String toString(boolean[] a) 返回指定數組的內容的字符串表示形式。 static String toString(byte[] a) 返回指定數組的內容的字符串表示形式。 static String toString(char[] a) 返回指定數組的內容的字符串表示形式。 static String toString(double[] a) 返回指定數組的內容的字符串表示形式。 static String toString(float[] a) 返回指定數組的內容的字符串表示形式。 static String toString(int[] a) 返回指定數組的內容的字符串表示形式。 static String toString(long[] a) 返回指定數組的內容的字符串表示形式。 static String toString(Object[] a) 返回指定數組的內容的字符串表示形式。 static String toString(short[] a) 返回指定數組的內容的字符串表示形式。 class example{public static void main(Sting[] args){Arrays.toString(數組名);} }2、數組排序
import java.util.Arrays;//導包 static void sort(byte[] a) 按照數字順序排列指定的數組。 static void sort(byte[] a, int fromIndex, int toIndex) 按升序排列數組的指定范圍。 static void sort(char[] a) 按照數字順序排列指定的數組。 static void sort(char[] a, int fromIndex, int toIndex) 按升序排列數組的指定范圍。 static void sort(double[] a) 按照數字順序排列指定的數組。 static void sort(double[] a, int fromIndex, int toIndex) 按升序排列數組的指定范圍。 static void sort(float[] a) 按照數字順序排列指定的數組。 static void sort(float[] a, int fromIndex, int toIndex) 按升序排列數組的指定范圍。 static void sort(int[] a) 按照數字順序排列指定的數組。 static void sort(int[] a, int fromIndex, int toIndex) 按升序排列數組的指定范圍。 static void sort(long[] a) 按照數字順序排列指定的數組。 static void sort(long[] a, int fromIndex, int toIndex) 按升序排列數組的指定范圍。 static void sort(Object[] a) 對指定對象升序排列的陣列,根據natural ordering的元素。 static void sort(Object[] a, int fromIndex, int toIndex) 對指定對象升序排列的數組的指定范圍內,根據natural ordering的元素。 static void sort(short[] a) 按照數字順序排列指定的數組。 static void sort(short[] a, int fromIndex, int toIndex) 按升序排列數組的指定范圍。 static <T> void sort(T[] a, Comparator<? super T> c) 根據指定的比較器引發的順序對指定的對象數組進行排序。 static <T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c) 根據指定的比較器引發的順序對指定的對象數組的指定范圍進行排序。 class example{public static void main(Sting[] args){Arrays.sort(數組名);} }3、數組長度
- 使用數組的length屬性
- 使用Array中的getLength方法
4、數組相等
- 使用數組自帶的equals方法
??
?實際上是使用Object類的equals()方法。
??
- 使用Arrays類中的equals方法
5、數組克隆
- new操作符的本意是分配內存。程序執行到new操作符時, 首先去看new操作符后面的類型,根據類型分配內存,再調用構造函數,填充對象的各個域,這一步就叫對象的初始化。初始化完畢后,可以把他的引用(地址)發布到外部,在外部就可以通過引用操縱這個對象。
- clone在第一步是和new相似的,都是分配內存,調用clone方法時,分配的內存和源對象一樣,然后再使用源對象中對應的各個域,填充新對象的域。同樣可以把這個新對象的引用發布到外部 。
??復制引用【直接賦值】
??復制對象【用clone方法】
- 使用基類 Object 的 clone()方法
- 使用Arrays的copyOf……系列方法
6、合并數組
- 使用Arrays中的copyOf方法
7、反轉數組
package test;/*** 數組的反轉*/ public class TestDemo {public static void main(String[] args) {int[] arr = new int[]{1,2,3,4,5,6};for(int elem:arr){System.out.print(elem + ",");}// 打印反轉后的元素arr = reverse(arr);System.out.println();for(int elem:arr){System.out.print(elem + ",");}}// 實現數組元素的翻轉public static int[] reverse(int[] arr){// 遍歷數組for(int i = 0;i < arr.length / 2;i++){// 交換元素int temp = arr[arr.length -i - 1];arr[arr.length -i - 1] = arr[i];arr[i] = temp;}// 返回反轉后的結果return arr;}// 第二種方式public static int[] reverse1(int[] arr){int[] arr1 = new int[arr.length];for(int i = arr.length-1;i >= 0;i--){arr1[arr.length-i-1] = arr[i];}return arr1;} }8、移除元素
- 通過創建新的數組,將保留的原數組中的元素賦值到新數組來實現原數組元素的刪除。同理,可以實現數組添加元素。
9、將數組元素組成一個字符串
- 遍歷數組
10、檢查數組是否包含某一個值
- 遍歷數組
11、ArrayList集合與Array數組相互轉化
-
Array: 讀快改慢
-
Linked :改快讀慢
-
Hash:介于兩者之間
三、面向對象程序設計
#mermaid-svg-aiADBokzsQ2unJeW {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-aiADBokzsQ2unJeW .error-icon{fill:#552222;}#mermaid-svg-aiADBokzsQ2unJeW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aiADBokzsQ2unJeW .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-aiADBokzsQ2unJeW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aiADBokzsQ2unJeW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aiADBokzsQ2unJeW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aiADBokzsQ2unJeW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aiADBokzsQ2unJeW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aiADBokzsQ2unJeW .marker.cross{stroke:#333333;}#mermaid-svg-aiADBokzsQ2unJeW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aiADBokzsQ2unJeW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-aiADBokzsQ2unJeW .cluster-label text{fill:#333;}#mermaid-svg-aiADBokzsQ2unJeW .cluster-label span{color:#333;}#mermaid-svg-aiADBokzsQ2unJeW .label text,#mermaid-svg-aiADBokzsQ2unJeW span{fill:#333;color:#333;}#mermaid-svg-aiADBokzsQ2unJeW .node rect,#mermaid-svg-aiADBokzsQ2unJeW .node circle,#mermaid-svg-aiADBokzsQ2unJeW .node ellipse,#mermaid-svg-aiADBokzsQ2unJeW .node polygon,#mermaid-svg-aiADBokzsQ2unJeW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aiADBokzsQ2unJeW .node .label{text-align:center;}#mermaid-svg-aiADBokzsQ2unJeW .node.clickable{cursor:pointer;}#mermaid-svg-aiADBokzsQ2unJeW .arrowheadPath{fill:#333333;}#mermaid-svg-aiADBokzsQ2unJeW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aiADBokzsQ2unJeW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aiADBokzsQ2unJeW .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-aiADBokzsQ2unJeW .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-aiADBokzsQ2unJeW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aiADBokzsQ2unJeW .cluster text{fill:#333;}#mermaid-svg-aiADBokzsQ2unJeW .cluster span{color:#333;}#mermaid-svg-aiADBokzsQ2unJeW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-aiADBokzsQ2unJeW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 面向對象程序設計 面向對象三大特性 類和對象 抽象類和接口 封裝 繼承 多態 類的定義 對象創建與使用 構造方法 內部類 關鍵字 抽象類 接口 抽象方法 抽象類 兩者區別??早期的程序經歷了【面向問題】、【面向過程】的階段,以往的程序設計方法不能適應現代的軟件的技術要求。故【面向對象】的程序設計方法被提出。
??面向對象的概念和應用已經超越了程序設計與開發,擴展到很寬的范圍,如數據庫系統、交互式界面、應用結構、應用平臺、分布式系統、網絡管理結構、CAD技術、人工智能等領域。
- 面向過程 (Procedure Oriented) ?以過程為核心,強調事件的流程、順序,如:C語言。
- 面向對象(Object Oriented) ?以對象為核心,強調事件的角色、主體,如:C++、Java。
- 總結 ?面向過程解決簡單問題效率高,面向對象有良好的繼承性、拓展性、復用性。
1、面向對象三大特性
1.1 封裝
- 把對象的屬性(成員變量)和行為(成員方法)看成一個密不可分的一個整體,將這兩者封裝在一個不可分割的獨立單位中(即對象)。
- 信息隱蔽,把不需要讓外界知道的信息隱蔽起來,有些對象的屬性和行為允許外界用戶知道或使用,但不允許修改。
- 具體表現?Java中通過將屬性的訪問權限聲明為私有的(private),再提供公共的(public)方法getXxx()和setXxx()實現對屬性的操作。
- IDEA中自動生成get/set方法
?lombok + @Data注解
??1)IDEA中安裝插件 lombok
??2)在類上方加上@Data注解
??IDEA自動生成
???1)在類內點擊 ctrl+回車
???2)選中Getter and Setter
???3)選中三個屬性,點擊 OK
???4)get和set方法自動出現
1.2 繼承
- 繼承又稱為派生。首先擁有反映事物一般特性的類,然后在此基礎上派生出反映特殊事物的類。
- 被繼承的類稱為父類或者超類,而經繼承產生的類稱為子類或派生類。
- 一個子類只允許繼承一個父類,稱為單繼承;允許繼承多個父類,稱為多繼承。目前許多面向對象語言不支持多繼承。而Java通過接口(interface)來彌補由于Java不支持多繼承而帶來的子類不能享用多個父類的成員的缺點。
- 關鍵詞extends
- 子類實際上是將父類定義的更加的具體化的一種手段。父類表示的范圍大,而子類表示的范圍小。
1.3 多態
- 指在父類中定義的屬性和方法被子類繼承之后,可以具有不同的數據類型或表現出不同的行為。
- JAVA中的多態可以簡單的理解為一種事物的多種形態,當然多態是在繼承的基礎上有重寫才存在。
??實現多態的必要條件 - 繼承
?在多態中必須存在有繼承關系的子類和父類。 - 重寫
?子類對父類中某些方法進行重新定義,在調用這些方法時就會調用子類的方法。 - 向上轉型
?在多態中需要將子類的引用賦給父類對象,只有這樣該引用才既能可以調用父類的方法,又能調用子類的方法。
?
?
多態的例子
?此案例很好的詮釋了多態性,子類向上轉型成相同名稱的對象,調用相同的方法,輸出不同的結果。
2、類和對象基礎知識
?在面向對象中類和對象是最基本、最重要的組成單元。
?類實際上表示一個客觀世界某類群體的一些基本特征抽象。
?對象是表示一個個具體的東西
- 類是對象的集合,對象是類的實例。
2.1 類的定義
?類是由屬性和方法組成的。
?實際上一個屬性就是一個變量,二方法就是一些操作的行為(也就是我們所說的函數);
?類的定義格式如下
2.2 對象的創建及使用
?需要通過對象來實例化類,即使用類;
?對象的創建
類實例化的內存分配詳解
Person p = new Person(); 的過程如下 存在繼承關系的Student stu = new Student(); 的過程如下2.3 構造方法
?構造方法是一個比較特殊的方法,通過構造方法可以完成對象的創建,以及實例變量的初始化。
?換句話說:構造方法是用來創建對象,并且同時給對象的屬性賦值。
?注意:實例變量沒有手動賦值的時候,系統會賦默認值。
?構造方法格式
- 當一個類中沒有提供任何構造方法,系統默認提供一個無參數的構造方法。
這個無參數的構造方法叫做缺省構造器。 - 當一個類中手動的提供了構造方法,那么系統將不再默認提供無參數構造方法。
建議將無參數構造方法手動的寫出來,這樣一定不會出問題。 - 構造方法是支持方法重載的。在一個類當中構造方法可以有多個。
并且所有的構造方法名字都是一樣的。 - 如果實例變量賦初始值,會在new對象的時候執行賦值,然后再執行構造方法里的代碼!!!
2.4 內部類
可以將一個類的定義放在里另一個類的內部,這就是內部類。廣義上我們將內部類分為四種:成員內部類、靜態內部類、局部(方法)內部類、匿名內部類。
/** * 我是一個外部類(外部是相對內部而言) */ public class Outer{/*** 我是一個內部類*/class Inner{//...} }使用內部類最吸引人的原因是:每個內部類都能獨立地繼承一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現,對于內部類都沒有影響。——《Think in java》
也就是說內部類擁有類的基本特征。(可以繼承父類,實現接口。)在實際問題中我們會遇到一些接口無法解決或難以解決的問題,此時我們可以使用內部類繼承某個具體的或抽象的類,間接解決類無法多繼承引起的一系列問題。(注:內部類可以嵌套內部類,但是這極大的破壞了代碼的結構,這里不推薦使用。)
/**1. Outer類繼承了ClassA,實現了IFunctionA */ public class Outer extends ClassA implements IFunctionA{ /*** Inner類繼承了ClassB,實現了IFunctionB*/public class Inner extends ClassB implements IfunctionB{//} }具體來說,內部類信息(屬性、方法)可以和外部類重名;
內部類是具有類的基本特征的獨立實體;
可以利用訪問修飾符隱藏內部類的實施細節,提供了更好的封裝;
靜態內部類使用時可直接使用,不需先創造外部類。
demo講解
- 成員內部類
1)外部類、內部類
??2)其他類使用成員內部類
/* * 其他類使用成員內部類*/ public class Other {public static void main(String[] args) {//外部類對象Outer outer = new Outer();//創造內部類對象Outer.Inner inner = outer.new Inner();inner.innerShow();/** 可在Outer中定義get方法,獲得Inner對象,那么使用時,只需outer.getInnerInstance()即可。* public Inner getInnerInstance(Inner類的構造方法參數){* return new Inner(參數);* }*/} }??3)運行結果(和innerShow()方法對照)
??4)小結——【成員內部類當成Outer的成員信息存在 】
- 可以是任何的訪問修飾符。
- 內部類的內部不能有靜態信息。
- 內部類也是類,該繼承繼承,該重寫重寫,該重載重載,this和super隨便用。
- 外部類如何訪問內部類信息,必須new之后打點訪問。
- 內部類可以直接使用外部類的任何信息,如果屬性或者方法發生沖突,調用外部類.this.屬性或者方法。
- 其它類如何訪問內部類:
- 靜態內部類
?1)外部類、內部類
??2)其他類使用成員內部類
public class Other {public static void main(String[] args) {//訪問靜態內部類的靜態方法,Inner類被加載,此時外部類未被加載,獨立存在,不依賴于外圍類。Outer.Inner.innerStaticShow();//訪問靜態內部類的成員方法Outer.Inner oi = new Outer.Inner();oi.innerShow();} }??3)運行結果(注意加載順序)
??4)小結——【和成員內部類對比理解(區別異同)】
- 內部可以包含任意的信息。
- 靜態內部類的方法只能訪問外部類的static關聯的信息。
- 利用 外部類.內部類 引用=new 外部類.內部類(); 然后利用引用.成員信息(屬性、方法)調用。
- 訪問內部類的靜態信息,直接外部類.內部類.靜態信息就可以了。
- 靜態內部類可以獨立存在,不依賴于其他外圍類。
- 局部內部類
?1)外部類、內部類
??2)運行結果
??3)小結——【局部內有很多局限,應注意作用域】
- 類前不能有訪問修飾符。
- 僅在此方法內使用。
- 無法創造靜態信息。
- 可以直接訪問方法內的局部變量和參數(有限制,下面詳談),但是不能更改。
- 可以隨意的訪問外部類的任何信息。
??
4)局部內部類訪問局部變量的限制
Variable ‘xxx’ is accessed from within inner class, needs to be final or effectively final
它的意思是:變量’xxx’從內部類中訪問,需要final或有效的final
??具體限制如下
??①直接被final修飾的變量。
??②已被賦值且始終未改變的變量(有且僅有賦值一次),引用指向不能改變。JDK8以前(不包括8)只能訪問被final修飾的變量。
??就會產生如下錯誤:傳入局部內部類所在方法的參數同理,如果一直不變則可使用,反之則會報錯。
- 匿名內部類
1)定義接口
??2)匿名內部類使用
/** * 外部內、內部類 */ public class Outer {public static IAnimal getInnerInstance(String speak){return new IAnimal(){@Overridepublic void speak(){System.out.println(speak);}};//注意上一行的分號必須有}public static void main(String[] args){//調用的speak()是重寫后的speak方法。Outer.getInnerInstance("小狗汪汪汪!").speak();} }??3)結果
小狗汪汪汪!
??4)小結——【匿名內部類常常被用來重寫某個或某些方法】
- 匿名內部類是沒有訪問修飾符的。
- 使用匿名內部類時,這個new之后的類首先是要存在的,其次我們要重寫new后的類的某個或某些方法。
- 匿名內部類訪問方法參數時也有和局部內部類同樣的限制。
- 匿名內部類沒有構造方法。
3、 幾個關鍵字
3.1 this關鍵字
- this關鍵字代表本類
- this關鍵字只能在方法內使用,方法外使用是編譯不通過的`
- this不能用于static方法中
- this可以作為方法的返回值。
1)this.屬性名
? this表示當前類,this.屬性名可以給當前類的屬性賦值,可以在本類中除靜態方法外的任何方法(包括構造器、私有方法)中使用。
?static關鍵字的特性
- 遵循靜態調用
- static關鍵字不能與this、super關鍵字共用
- 注意:若本類成員變量與方法內局部變量同名,this.屬性名代表的是什么呢??
解答:是局部變量,因為Java遵循就近原則,通俗地講,誰離我近,我就代表誰。
2)this.方法
?this.方法 即調用方法,除了靜態方法中不可使用,本類其他方法包括私有方法均可使用此格式調用其他方法,只是我們通常省略this關鍵字。
class Student{String name;public void hello(){this.name=name;} // this.name=name;this需要在方法內使用public void hi(){this.hello();hello();he();}private void he(){this.name=name;hello();this.he();} }3)this.()
此格式用于構造器內
- 比如我們可以在無參構造內調用含參構造,那么這時候就需要在this()傳入參數來實現,
- 同理要想在含參構造內調用無參構造,只需在構造器代碼第一行寫this()即可,
- 注意,this()與this(參數列表)不可同時使用!
3.2 super關鍵字
- super理解為:超類的,父類的
- super可以用來調用:屬性、方法、構造器
- super的語法是: “super.屬性名/方法”、“super()”
1)super()
- 創建子類對象的時候,先初始化父類型特征。
- 在構造方法中使用
- super(實際參數列表)的作用是:初始化當前對象的父類型特征。
并不是創建新對象。實際上對象只創建了一個。 - 在構造方法執行過程中一連串調用了父類的構造方法,父類的構造方法又繼續向下調用它的父類的構造方法。
- super關鍵字代表的就是當前對象的那部分父類型特征。
2)super.屬性名/方法
- 訪問父類的屬性和方法
- super.大部分情況下是可以省略的。
- super.什么時候不能省略呢?
父中有,子中又有,如果想在子中訪問父的特征,super. 不能省略。
在 父和子中 有同名的屬性,或者說有相同的方法,
如果此時想在子類中訪問父中的數據,必須使用super.加以區分。
3)super關鍵字和this關鍵字重要結論
- 當一個構造方法第一行:既沒有this()又沒有super()的話,默認會有一個super();
通過當前子類的構造方法調用父類的無參數構造方法。所以必須保證父類的無參數構造方法是存在的。 - 在java語言中不管是是new什么對象,最后老祖宗的Object類的無參數構造方法一定會執行。
- this() 和 super() 不能共存,它們都是只能出現在構造方法第一行。
- 無論是怎樣折騰,父類的構造方法是一定會執行的。
- this是引用。this也保存內存地址,this也指向任何對象。
- super 不是引用。super也不保存內存地址,super也不指向任何對象。
super 只是代表當前對象內部的那一塊父類型的特征。
3.3 instanceof關鍵字
- instanceof關鍵字,用于判斷某一個類是否繼承自另一個類,即驗證兩個類之間是否屬于父類和子類的關系。
- instanceof關鍵字判斷后是有返回值的且返回值為boolean類型。
- 語法格式
4、抽象類和接口
?對于面向對象編程來說,抽象是它的一大特征之一。在Java中,可以通過兩種形式來體現OOP的抽象:接口和抽象類。這兩者有太多相似的地方,又有太多不同的地方。
4.1 抽象類
1)抽象方法
- 是一種特殊的方法:只有聲明,而沒有具體的實現。
- 聲明格式
2)抽象類
- 如果一個類含有抽象方法,則稱這個類為抽象類
- 抽象類必須在類前用abstract關鍵字修飾。
- 因為抽象類中含有無具體實現的方法,所以不能用抽象類創建對象。
將抽象類定義為“包含抽象方法的類” ——《JAVA編程思想》
- 語法格式
- 從這里可以看出,抽象類就是為了繼承而存在的
- 實際需求
對于一個父類,如果它的某個方法在父類中實現出來沒有任何意義,必須根據子類的實際需求來進行不同的實現,那么就可以將這個方法聲明為abstract方法,此時這個類也就成為abstract類了。 - 包含抽象方法的類稱為抽象類,但并不意味著抽象類中只能有抽象方法,它和普通類一樣,同樣可以擁有成員變量和普通的成員方法。
- 與普通類的區別
?抽象方法必須為public或者protected(因為如果為private,則不能被子類繼承,子類便無法實現該方法),缺省情況下默認為public。
?抽象類不能用來創建對象;
?如果一個類繼承于一個抽象類,則子類必須實現父類的抽象方法。如果子類沒有實現父類的抽象方法,則必須將子類也定義為abstract類。
4.2 接口
?接口,英文稱作interface,在軟件工程中,接口泛指供別人調用的方法或者函數。從這里,我們可以體會到Java語言設計者的初衷,它是對行為的抽象。
- 語法格式
- 接口中可以含有 變量和方法
? 接口中的變量會被隱式地指定為public static final變量(并且只能是public static final變量,用private修飾會報編譯錯誤)
? 方法會被隱式地指定為public abstract方法且只能是public abstract方法(用其他關鍵字,比如private、protected、static、 final等修飾會報編譯錯誤)
? 接口中所有的方法不能有具體的實現,也就是說,接口中的方法必須都是抽象方法。 - 要讓一個類遵循某組特地的接口需要使用implements關鍵字,具體格式如下
- 可以看出
?允許一個類實現多個特定的接口【實現多繼承】
?如果一個非抽象類遵循了某個接口,就必須實現該接口中的所有抽象方法。
?對于遵循某個接口的抽象類,可以不實現該接口中的抽象方法。
4.3 抽象類和接口的區別
1)語法層面
- 抽象類可以提供成員方法的實現細節,而接口中只能存在public abstract 方法;
- 抽象類中的成員變量可以是各種類型的,而接口中的成員變量只能是public static final類型的;
- 接口中不能含有靜態代碼塊以及靜態方法,而抽象類可以有靜態代碼塊和靜態方法;
- 一個類只能繼承一個抽象類,而一個類卻可以實現多個接口。
?抽象類用繼承,接口用實現
2)設計層面
- 抽象類是對一種事物的抽象,即對類抽象,而接口是對行為的抽象。
- 抽象類是對整個類整體進行抽象,包括屬性、行為,但是接口卻是對類局部(行為)進行抽象。
- 對比表
?接口比抽象類更加嚴格,但接口是實現多繼承的方式。
| 默認的方法實現 | 它可以有默認的方法實現 | 接口完全是抽象的。它根本不存在方法的實現 |
| 實現 | 子類使用extends關鍵字來繼承抽象類。如果子類不是抽象類的話,它需要提供抽象類中所有聲明的方法的實現。 | 子類使用關鍵字implements來實現接口。它需要提供接口中所有聲明的方法的實現 |
| 構造器 | 抽象類可以有構造器 | 接口不能有構造器 |
| 與正常Java類的區別 | 除了你不能實例化抽象類之外,它和普通Java類沒有任何區別 | 接口是完全不同的類型 |
| 訪問修飾符 | 抽象方法可以有public、protected和default這些修飾符 | 接口方法默認修飾符是public。你不可以使用其它修飾符。 |
| main方法 | 抽象方法可以有main方法并且我們可以運行它 | 接口沒有main方法,因此我們不能運行它。 |
| 多繼承 | 抽象方法可以繼承一個類和實現多個接口 | 接口只可以繼承一個或多個其它接口 |
| 速度 | 它比接口速度要快 | 接口是稍微有點慢的,因為它需要時間去尋找在類中實現的方法。 |
| 添加新方法 | 如果你往抽象類中添加新的方法,你可以給它提供默認的實現。因此你不需要改變你現在的代碼。 | 如果你往接口中添加方法,那么你必須改變實現該接口的類。 |
總結
以上是生活随笔為你收集整理的Java剑开天门(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 龙威ol服务器维护是什么意思,《龙威OL
- 下一篇: Docker创始人兼CTO宣布离职;特斯