日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java剑开天门(二)

發布時間:2024/3/13 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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開始,側重學習一維數組

  • 一維數組
1)動態初始化格式 數據類型 [] 數組名稱 = new 數據類型[數組長度];2)靜態初始化格式 數據類型 [] 數組名稱 = new 數據類型[]{元素1,元素2,元素3};3)靜態初始化省略格式 數據類型 [] 數組名稱 = {元素1,元素2,元素3};
  • 二維數組
    ?如果把一維數組比作幾何圖形中的線性圖形,那么二維數組就相當于一個表格
    ?左索引代表行,右索引代表列
1)動態初始化格式 數據類型 [][] 數組名稱 = new 數據類型[行的個數][列的個數];2)靜態初始化格式 數據類型 [][] 數組名稱 = new 數據類型[][]{{元素1,元素2,元素3},{元素1,元素2,元素3},……}; //內大括號代表一行,內大括號里的每一元素代表一列; //根據內大括號個數確定行數,根據內大括號里元素個數確定列數; 3)靜態初始化省略格式 數據類型 [][] 數組名稱 ={{元素1,元素2,元素3},{元素1,元素2,元素3},……};
  • 多維數組
    ?只需在聲明數組時將索引與中括號再加一組就可提高數組的維數。
    ?如三維數組? 數據類型 ?[][][] ?數組名稱=new? 數據類型 ?[個數][個數][個數] ;

1.3 方法定義

  • 解決某件事的功能實現。
  • 是一段代碼塊的封裝,是某一功能的實現。
    ? 語法格式
修飾符 返回值類型 方法名(參數類型 參數名1,參數類型 參數名2,......){ 執行語句包括1)方法的調用2)變量的操作:聲明 賦值 修改3)程序結構:順序結構 選擇結構 循環結構 return 返回值; }
  • 修飾符
    這是可選的,告訴編譯器如何調用該方法,定義了該方法的訪問類型。
    ? 訪問控制權限修飾符
    ? 訪問控制權限修飾符來控制元素的訪問范圍。
    ? ? 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屬性
import java.lang.*;//導包 class example{public static void main(Sting[] args){for(int i=0;i<數組名.length;i++){……}} }
  • 使用Array中的getLength方法
import java.lang.reflect.Array;//導包 static int getLength(Object array) 返回指定數組對象的長度,如 intclass example{public static void main(Sting[] args){for(int i=0;i<Array.getLength(數組名);i++){//Array.getLength()……}} }

4、數組相等

  • 使用數組自帶的equals方法
    ??
    ?實際上是使用Object類的equals()方法。
    ??
import java.lang.*;//導包 class example{public static void main(Sting[] args){數組名.equals(另一數組名);//結果為true或false} }
  • 使用Arrays類中的equals方法
import java.util.Arrays;//導包 static boolean equals(boolean[] a, boolean[] a2) 如果兩個指定的布爾數組彼此 相等 ,則返回 truestatic boolean equals(byte[] a, byte[] a2) 如果兩個指定的字節數組彼此 相等 ,則返回 truestatic boolean equals(char[] a, char[] a2) 如果兩個指定的字符數組彼此 相等 ,則返回 truestatic boolean equals(double[] a, double[] a2) 如果兩個指定的雙精度數組彼此 相等 ,則返回 truestatic boolean equals(float[] a, float[] a2) 如果兩個指定的浮動數組彼此 相等 ,則返回 truestatic boolean equals(int[] a, int[] a2) 如果兩個指定的int數組彼此 相等 ,則返回 truestatic boolean equals(long[] a, long[] a2) 如果兩個指定的longs數組彼此 相等 ,則返回 truestatic boolean equals(Object[] a, Object[] a2) 如果兩個指定的對象數組彼此 相等 ,則返回 truestatic boolean equals(short[] a, short[] a2) 如果兩個指定的短褲陣列彼此 相等 ,則返回 true class example{public static void main(Sting[] args){Arrays.equals(數組名,另一數組名);//結果為true或false} }

5、數組克隆

  • new操作符的本意是分配內存。程序執行到new操作符時, 首先去看new操作符后面的類型,根據類型分配內存,再調用構造函數,填充對象的各個域,這一步就叫對象的初始化。初始化完畢后,可以把他的引用(地址)發布到外部,在外部就可以通過引用操縱這個對象。
  • clone在第一步是和new相似的,都是分配內存,調用clone方法時,分配的內存和源對象一樣,然后再使用源對象中對應的各個域,填充新對象的域。同樣可以把這個新對象的引用發布到外部 。
    ??復制引用【直接賦值】

    ??復制對象【用clone方法】

  • 使用基類 Object 的 clone()方法
import java.lang.*;//導包 class example{public static void main(Sting[] args){int[] src={1,2,3};int[] copy=src.clone();} }
  • 使用Arrays的copyOf……系列方法
import java.util.Arrays;//導包 class example{public static void main(Sting[] args){Arrays.copyOf(數組名,數組名.length);} } static boolean[] copyOf(boolean[] original, int newLength) 使用 false (如有必要)復制指定的數組,截斷或填充,以使副本具有指定的長度。 static byte[] copyOf(byte[] original, int newLength) 復制指定的數組,用零截取或填充(如有必要),以便復制具有指定的長度。 static char[] copyOf(char[] original, int newLength) 復制指定的數組,截斷或填充空字符(如有必要),以便復制具有指定的長度。 static double[] copyOf(double[] original, int newLength) 復制指定的數組,用零截取或填充(如有必要),以便復制具有指定的長度。 static float[] copyOf(float[] original, int newLength) 復制指定的數組,用零截取或填充(如有必要),以便復制具有指定的長度。 static int[] copyOf(int[] original, int newLength) 復制指定的數組,用零截取或填充(如有必要),以便復制具有指定的長度。 static long[] copyOf(long[] original, int newLength) 復制指定的數組,用零截取或填充(如有必要),以便復制具有指定的長度。 static short[] copyOf(short[] original, int newLength) 復制指定的數組,用零截取或填充(如有必要),以便復制具有指定的長度。 static <T> T[] copyOf(T[] original, int newLength) 復制指定的數組,用空值截斷或填充(如有必要),以便復制具有指定的長度。 static <T,U> T[] copyOf(U[] original, int newLength,<? extends T[]> newType) 復制指定的數組,用空值截斷或填充(如有必要),以便復制具有指定的長度。 static boolean[] copyOfRange(boolean[] original, int from, int to) 將指定數組的指定范圍復制到新數組中。 static byte[] copyOfRange(byte[] original, int from, int to) 將指定數組的指定范圍復制到新數組中。 static char[] copyOfRange(char[] original, int from, int to) 將指定數組的指定范圍復制到新數組中。 static double[] copyOfRange(double[] original, int from, int to) 將指定數組的指定范圍復制到新數組中。 static float[] copyOfRange(float[] original, int from, int to) 將指定數組的指定范圍復制到新數組中。 static int[] copyOfRange(int[] original, int from, int to) 將指定數組的指定范圍復制到新數組中。 static long[] copyOfRange(long[] original, int from, int to) 將指定數組的指定范圍復制到新數組中。 static short[] copyOfRange(short[] original, int from, int to) 將指定數組的指定范圍復制到新數組中。 static <T> T[] copyOfRange(T[] original, int from, int to) 將指定數組的指定范圍復制到新數組中。 static <T,U> T[] copyOfRange(U[] original, int from, int to,<? extends T[]> newType) 將指定數組的指定范圍復制到新數組中。

6、合并數組

  • 使用Arrays中的copyOf方法
import java.util.Arrays;//導包 public class example{public static void main(String[] args){int[] A=new int[]{1,3,5,7,9};int[] B=new int[]{2,4,6,8,10};int[] result=Arrays.copyOf(A,10);//使result數組長度為10,并將A數組拷貝至新數組,此時result數組與原數組不是同一塊內存,原來的內存還是5個元素,result的是擴容后的空間for(int x=0;x<B.length;x++){result[A.length+x]=B[x];}for(int i:result){System.out.print(i+" ");}System.out.print("");//換行} }

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、移除元素

  • 通過創建新的數組,將保留的原數組中的元素賦值到新數組來實現原數組元素的刪除。同理,可以實現數組添加元素。
package package1;import java.util.Arrays;public class example {public static void main(String[] args) {int[] array1 = new int[] {4, 5, 6, 7};int num = 2;int[] newArray = new int[array1.length-1];for(int i=0;i<newArray.length; i++) {// 判斷元素是否越界if (num < 0 || num >= array1.length) {throw new RuntimeException("元素越界... "); } // if(i<num) {newArray[i] = array1[i];}else {newArray[i] = array1[i+1];}}// 打印輸出數組內容System.out.println(Arrays.toString(array1));array1 = newArray;System.out.println(Arrays.toString(array1));} }

9、將數組元素組成一個字符串

  • 遍歷數組
import java.util.Arrays; public class example{public static void main(String[] args){// TODO Auto-generated method stub//定義一個int類型的數組int[] i ={4,5,8,6,5,8,7,4,5};//調用自定義方法將int數組的方法轉換成字符串toStringMethod(i);}private static void toStringMethod(int[] arr){// 自定義一個字符緩沖區,StringBuilder sb = new StringBuilder();sb.append("[ ");//遍歷int數組,并將int數組中的元素轉換成字符串儲存到字符緩沖區中去for(int i=0;i<sb.length;i++){if(i!=arr.length-1){sb.append(arr[i]+" ,");else{sb.append(arr[i]+" ]");}System.out.println(sb);}}

10、檢查數組是否包含某一個值

  • 遍歷數組
import java.util.Arrays; public class example{public static void main(String[] args){String[] vowels = { "A", "I", "E", "O", "U" };// using simple iteration over the array elementsfor (String s : vowels) {if ("E".equals(s)) {System.out.println("E found in the vowels list.");}}} }

11、ArrayList集合與Array數組相互轉化

  • Array: 讀快改慢

  • Linked :改快讀慢

  • Hash:介于兩者之間

//集合轉數組,集合中toArray()的方法import java.util.*;public class example {public static void main(String[] arr) {Object[] listArray = list.toArray();Object[] setArray = set.toArray();} } //數組轉集合,Arrays.asList(數組名)方法import java.util.*;public class example {public static void main(String[] arr) {List list = new ArrayList();list = Arrays.asList(array); //注意:對于int[]數組不能直接這樣做,因為asList()方法的參數必須是對象。應該先把int[]轉化為Integer[]。Set set = new HashSet(Array.asList(array)); //使用list構造set} }

三、面向對象程序設計

#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注解
package com.my.app.xxx;@Data public class Student {private String name;private int age;private String grade; }

??IDEA自動生成
???1)在類內點擊 ctrl+回車
???2)選中Getter and Setter

???3)選中三個屬性,點擊 OK


???4)get和set方法自動出現

package com.my.app.model;/*** Description TODO*/ public class Student {private String name;private int age;private String grade;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGrade() {return grade;}public void setGrade(String grade) {this.grade = grade;} }

1.2 繼承

  • 繼承又稱為派生。首先擁有反映事物一般特性的類,然后在此基礎上派生出反映特殊事物的類。
  • 被繼承的類稱為父類或者超類,而經繼承產生的類稱為子類或派生類。
  • 一個子類只允許繼承一個父類,稱為單繼承;允許繼承多個父類,稱為多繼承。目前許多面向對象語言不支持多繼承。而Java通過接口(interface)來彌補由于Java不支持多繼承而帶來的子類不能享用多個父類的成員的缺點。
  • 關鍵詞extends
class 子類 extends 父類 {}
  • 子類實際上是將父類定義的更加的具體化的一種手段。父類表示的范圍大,而子類表示的范圍小。

1.3 多態

  • 指在父類中定義的屬性和方法被子類繼承之后,可以具有不同的數據類型或表現出不同的行為。
  • JAVA中的多態可以簡單的理解為一種事物的多種形態,當然多態是在繼承的基礎上有重寫才存在。
    ??實現多態的必要條件
  • 繼承
    ?在多態中必須存在有繼承關系的子類和父類。
  • 重寫
    ?子類對父類中某些方法進行重新定義,在調用這些方法時就會調用子類的方法。
  • 向上轉型
    ?在多態中需要將子類的引用賦給父類對象,只有這樣該引用才既能可以調用父類的方法,又能調用子類的方法。
    ?
    ?
    多態的例子
1)創建 Figure 類,在該類中首先定義存儲二維對象的尺寸, 然后定義有兩個參數的構造方法,最后添加 area() 方法,該方法計算對象的面積。 代碼如下 public class Figure {double dim1;double dim2;Figure(double d1, double d2) {// 有參的構造方法this.dim1 = d1;this.dim2 = d2;}double area() {// 用于計算對象的面積System.out.println("父類中計算對象面積的方法,沒有實際意義,需要在子類中重寫。");return 0;} } 2)創建繼承自 Figure 類的 Rectangle 子類, 該類調用父類的構造方法,并且重寫父類中的 area() 方法。 代碼如下 public class Rectangle extends Figure {Rectangle(double d1, double d2) {super(d1, d2);}double area() {System.out.println("長方形的面積:");return super.dim1 * super.dim2;} } 3)創建繼承自 Figure 類的 Triangle 子類,該類與 Rectangle 相似。 代碼如下 public class Triangle extends Figure {Triangle(double d1, double d2) {super(d1, d2);}double area() {System.out.println("三角形的面積:");return super.dim1 * super.dim2 / 2;} } 4)創建 Test 測試類,在該類的 main() 方法中首先聲明 Figure 類的變量 figure, 然后分別為 figure 變量指定不同的對象,并調用這些對象的 area() 方法。 代碼如下 public class Test {public static void main(String[] args) {Figure figure; // 聲明Figure類的變量figure = new Rectangle(9, 9);System.out.println(figure.area());System.out.println("===============================");figure = new Triangle(6, 8);System.out.println(figure.area());System.out.println("===============================");figure = new Figure(10, 10);System.out.println(figure.area());} }_ooOoo_ o8888888o 88" . "88 (| -_- |) O\ = /O ____/`---'\____ .' \\| |// `. / \\||| : |||// \ / _||||| -:- |||||_ \ | | \\\ - /'| | | | \_| `\`---'// |_/ | \ .-\__ `-. -'__/-. / ___`. .' /--.--\ `. .'___ ."" '< `.___\_<|>_/___.' _> \"". | | : `- \`. ;`. _/; .'/ / .' ; | \ \ `-. \_\_`. _.'_/_/ -' _.' / ================-.`___`-.__\ \___ /__.-'_.'_.-'================ `=--=-' 輸出 長方形的面積: 81.0 =============================== 三角形的面積: 24.0 =============================== 父類中計算對象面積的方法,沒有實際意義,需要在子類中重寫。 0.0

?此案例很好的詮釋了多態性,子類向上轉型成相同名稱的對象,調用相同的方法,輸出不同的結果。

2、類和對象基礎知識

?在面向對象中類和對象是最基本、最重要的組成單元。
?類實際上表示一個客觀世界某類群體的一些基本特征抽象。
?對象是表示一個個具體的東西

  • 類是對象的集合,對象是類的實例。

2.1 類的定義

?類是由屬性和方法組成的。
?實際上一個屬性就是一個變量,二方法就是一些操作的行為(也就是我們所說的函數);
?類的定義格式如下

修飾符 class 類名{修飾符 數據類型 屬性;修飾符 數據類型 屬性;修飾符 數據類型 屬性;……修飾符 返回值類型 方法名(參數1,參數2,……){程序語句;[return 表達式; ]}}

2.2 對象的創建及使用

?需要通過對象來實例化類,即使用類;
?對象的創建

類名 對象名稱= new 類名();//只要有關鍵字new就表示開辟新的堆內存空間 訪問對象中的屬性和方法 【訪問屬性】——對象名稱.屬性名 【訪問方法】——對象名稱.方法名() 創建對象的五種方法 —————————————————————————————————————————————————————————————————————— 1)使用new關鍵字創建對象 這是我們最常見的也是最簡單的創建對象的方式, 通過這種方式我們可以調用任意的構造函數(無參的和有參的)去創建對象。 比如 Student student = new Student(); —————————————————————————————————————————————————————————————————————— 2)使用Class類的newInstance方法(反射機制)創建對象 我們也可以通過Java的反射機制使用Class類的newInstance方法來創建對象, 事實上,這個newInstance方法調用無參的構造器創建對象, 比如 Student student2 = (Student)Class.forName("Student類全限定名").newInstance();  或者 Student stu = Student.class.newInstance(); —————————————————————————————————————————————————————————————————————— 3)使用Constructor類的newInstance方法(反射機制)創建對象 java.lang.relect.Constructor類里也有一個newInstance方法可以創建對象, 該方法和Class類中的newInstance方法很像,但是相比之下, Constructor類的newInstance方法更加強大些, 我們可以通過這個newInstance方法調用有參數的和私有的構造函數, 比如 public class Student {private int id;public Student(Integer id) {this.id = id;}public static void main(String[] args) throws Exception {Constructor<Student> constructor = Student.class.getConstructor(Integer.class);Student stu3 = constructor.newInstance(123);} } —————————————————————————————————————————————————————————————————————— 4)使用Clone方法創建對象無論何時我們調用一個對象的clone方法,JVM都會幫我們創建一個新的、一樣的對象,特別需要說明的是,用clone方法創建對象的過程中并不會調用任何構造函數。簡單而言,要想使用clone方法,我們就必須先實現Cloneable接口并實現其定義的clone方法,這也是原型模式的應用。比如public class Student implements Cloneable{private int id;public Student(Integer id) {this.id = id;}@Overrideprotected Object clone() throws CloneNotSupportedException {// TODO Auto-generated method stubreturn super.clone();}public static void main(String[] args) throws Exception {Constructor<Student> constructor = Student.class.getConstructor(Integer.class);Student stu3 = constructor.newInstance(123);Student stu4 = (Student) stu3.clone();} } —————————————————————————————————————————————————————————————————————— 5)使用()序列化機制創建對象當我們反序列化一個對象時,JVM會給我們創建一個單獨的對象,在此過程中,JVM并不會調用任何構造函數。為了反序列化一個對象,我們需要讓我們的類實現Serializable接口,比如public class Student implements Cloneable, Serializable {private int id;public Student(Integer id) {this.id = id;}@Overridepublic String toString() {return "Student [id=" + id + "]";}public static void main(String[] args) throws Exception {Constructor<Student> constructor = Student.class.getConstructor(Integer.class);Student stu3 = constructor.newInstance(123);// 寫對象ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("student.bin"));output.writeObject(stu3);output.close();// 讀對象ObjectInputStream input = new ObjectInputStream(new FileInputStream("student.bin"));Student stu5 = (Student) input.readObject();System.out.println(stu5);} }

類實例化的內存分配詳解

Person p = new Person(); 的過程如下

存在繼承關系的Student stu = new Student(); 的過程如下

2.3 構造方法

?構造方法是一個比較特殊的方法,通過構造方法可以完成對象的創建,以及實例變量的初始化。
?換句話說:構造方法是用來創建對象,并且同時給對象的屬性賦值。
?注意:實例變量沒有手動賦值的時候,系統會賦默認值。
?構造方法格式

[修飾符列表] 構造方法名(形式參數列表){構造方法體;通常在構造方法體當中給屬性賦值,完成屬性的初始化。 } 注意點 1)修飾符列表目前統一寫:public。千萬不要寫public static2)構造方法名和類名必須一致。 3)構造方法不需要【指定返回值類型】, 也不能寫void,寫上void表示普通方法,就不是構造方法了。在對象創建時,使用new運算符來調用構造方法。 new 構造方法名(實際參數列表);
  • 當一個類中沒有提供任何構造方法,系統默認提供一個無參數的構造方法。
    這個無參數的構造方法叫做缺省構造器。
  • 當一個類中手動的提供了構造方法,那么系統將不再默認提供無參數構造方法。
    建議將無參數構造方法手動的寫出來,這樣一定不會出問題。
  • 構造方法是支持方法重載的。在一個類當中構造方法可以有多個。
    并且所有的構造方法名字都是一樣的。
  • 如果實例變量賦初始值,會在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)外部類、內部類
/*** 外部類、成員內部類的定義*/ public class Outer {private int outerVariable = 1;private int commonVariable = 2;private static int outerStaticVariable = 3;//省略getter/setter/*** 成員方法*/public void outerMethod() {System.out.println("我是外部類的outerMethod方法");}/*** 靜態方法*/public static void outerStaticMethod() {System.out.println("我是外部類的outerStaticMethod靜態方法");}/*** 內部類*/public class Inner {private int commonVariable = 20;/*** 構造方法*/public Inner() {}/*** 成員方法,訪問外部類信息(屬性、方法)*/public void innerShow() {//當和外部類沖突時,直接引用屬性名,是內部類的成員屬性System.out.println("內部的commonVariable:" + commonVariable);//內部類訪問外部屬性System.out.println("outerVariable:" + outerVariable);//當和外部類屬性名重疊時,可通過外部類名.this.屬性名System.out.println("外部的commonVariable:" + Outer.this.commonVariable);System.out.println("outerStaticVariable:" + outerStaticVariable);//訪問外部類的方法outerMethod();outerStaticMethod();}}/*** 外部類訪問內部類信息*/public void outerShow() {Inner inner = new Inner();inner.innerShow();} }

??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.屬性或者方法。
  • 其它類如何訪問內部類:
Outer outer=new Outer();//創造內部類對象Outer.Inner inner=outer.new Inner();inner.inner_show();
  • 靜態內部類
    ?1)外部類、內部類
/*** 外部類、內部類定義*/ public class Outer {private int outerVariable = 1;/*** 外部類定義的屬性(重名)*/private int commonVariable = 2;private static int outerStaticVariable = 3;static {System.out.println("Outer的靜態塊被執行了……");}/*** 成員方法*/public void outerMothod() {System.out.println("我是外部類的outerMethod方法");}/** 靜態方法*/public static void outerStaticMethod() {System.out.println("我是外部類的outerStaticMethod靜態方法");}/*** 靜態內部類*/public static class Inner {/*** 成員信息*/private int innerVariable = 10;private int commonVariable = 20;static {System.out.println("Outer.Inner的靜態塊執行了……");}private static int innerStaticVariable = 30;/*** 成員方法*/public void innerShow() {System.out.println("innerVariable:" + innerVariable);System.out.println("內部的commonVariable:" + commonVariable);System.out.println("outerStaticVariable:"+outerStaticVariable);outerStaticMethod();}/*** 靜態方法*/public static void innerStaticShow() {//被調用時會先加載Outer類outerStaticMethod();System.out.println("outerStaticVariable"+outerStaticVariable);}}/*** 外部類的內部如何和內部類打交道*/public static void callInner() {System.out.println(Inner.innerStaticVariable);Inner.innerStaticShow();} }

??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)外部類、內部類
/*** 外部類、內部類*/ public class Outer {/*** 屬性和方法*/private int outerVariable = 1;/*** 外部類定義的屬性*/private int commonVariable = 2;/*** 靜態的信息*/private static int outerStaticVariable = 3;/*** 成員外部方法*/public void outerMethod() {System.out.println("我是外部類的outerMethod方法");}/*** 靜態外部方法*/public static void outerStaticMethod() {System.out.println("我是外部類的outerStaticMethod靜態方法");}/*** 程序的入口*/public static void main(String[] args) {Outer outer = new Outer();outer.outerCreatMethod(100);}/*** 成員方法,內部定義局部內部類*/public void outerCreatMethod(int value) {/*** 女性*/boolean sex = false;/*** 局部內部類,類前不能有訪問修飾符*/class Inner {private int innerVariable = 10;private int commonVariable = 20;/*** 局部內部類方法*/public void innerShow() {System.out.println("innerVariable:" + innerVariable);//局部變量System.out.println("是否男性:" + sex);System.out.println("參數value:" + value);//調用外部類的信息System.out.println("outerVariable:" + outerVariable);System.out.println("內部的commonVariable:" + commonVariable);System.out.println("外部的commonVariable:" + Outer.this.commonVariable);System.out.println("outerStaticVariable:" + outerStaticVariable);outerMethod();outerStaticMethod();}}//局部內部類只能在方法內使用Inner inner = new Inner();inner.innerShow();} }

??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修飾的變量。

boolean sex=false; sex=true;

??就會產生如下錯誤:傳入局部內部類所在方法的參數同理,如果一直不變則可使用,反之則會報錯。


  • 匿名內部類
    1)定義接口
/** * 接口中方法默認為public */ public interface IAnimal{void speak(); }

??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可以作為方法的返回值。
private rolecolor = red;public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);if (isSelected) {setBackground(this.rowcolor);setFont(getFont().deriveFont((float) (getFont().getSize() + 2)));}return this;//返回當前JList對象 }

1)this.屬性名

? this表示當前類,this.屬性名可以給當前類的屬性賦值,可以在本類中除靜態方法外的任何方法(包括構造器、私有方法)中使用。
?static關鍵字的特性

  • 遵循靜態調用
  • static關鍵字不能與this、super關鍵字共用
  • 注意:若本類成員變量與方法內局部變量同名,this.屬性名代表的是什么呢??
    解答:是局部變量,因為Java遵循就近原則,通俗地講,誰離我近,我就代表誰。
class Student{String name;public void hello(){this.name=name;} }

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(參數列表)不可同時使用!
public Student(){this("name");this.name=name;// this.(); } public Student(String name){ // this();兩個this不能一起使用}

3.2 super關鍵字

  • super理解為:超類的,父類的
  • super可以用來調用:屬性、方法、構造器
  • super的語法是: “super.屬性名/方法”、“super()”

1)super()

  • 創建子類對象的時候,先初始化父類型特征。
  • 在構造方法中使用
  • super(實際參數列表)的作用是:初始化當前對象的父類型特征。
    并不是創建新對象。實際上對象只創建了一個。
  • 在構造方法執行過程中一連串調用了父類的構造方法,父類的構造方法又繼續向下調用它的父類的構造方法。
  • super關鍵字代表的就是當前對象的那部分父類型特征。
public class SuperTest03{public static void main(String[] args){CreditAccount ca1 = new CreditAccount();System.out.println(ca1.getActno() + "," + ca1.getBalance() + "," + ca1.getCredit());CreditAccount ca2 = new CreditAccount("1111", 10000.0, 0.999);System.out.println(ca2.getActno() + "," + ca2.getBalance() + "," + ca2.getCredit());} }// 賬戶 class Account extends Object{// 屬性private String actno;private double balance;// 構造方法public Account(){//默認有以下代碼//super();//this.actno = null;//this.balance = 0.0;}public Account(String actno, double balance){// super();this.actno = actno;this.balance = balance;}// setter and getterpublic void setActno(String actno){this.actno = actno;}public String getActno(){return actno;}public void setBalance(double balance){this.balance = balance;}public double getBalance(){return balance;} }// 信用賬戶 class CreditAccount extends Account{// 屬性:信譽度(誠信值)// 子類特有的一個特征,父類沒有。private double credit;// 構造方法// 分析以下程序是否存在編譯錯誤????public CreditAccount(String actno, double balance, double credit){// 私有的屬性,只能在本類中訪問。/*this.actno = actno;this.balance = balance;*/// 以上兩行代碼在恰當的位置,正好可以使用:super(actno, balance);// 通過子類的構造方法調用父類的構造方法。super(actno, balance);this.credit = credit;}// 提供有參數的構造方法public CreditAccount(){//super();//this.credit = 0.0;}// setter and getter方法public void setCredit(double credit){this.credit = credit;}public double getCredit(){return credit;}}

2)super.屬性名/方法

  • 訪問父類的屬性和方法
  • super.大部分情況下是可以省略的。
  • super.什么時候不能省略呢?
    父中有,子中又有,如果想在子中訪問父的特征,super. 不能省略。
    在 父和子中 有同名的屬性,或者說有相同的方法,
    如果此時想在子類中訪問父中的數據,必須使用super.加以區分。
class Animal{public void move(){System.out.println("Animal move!");} }class Cat extends Animal{// 對move進行重寫。public void move(){System.out.println("Cat move!");}// 單獨編寫一個子類特有的方法。public void yiDong(){this.move();//子類的move//前面不寫默認有this.move();//子類的move// super. 不僅可以訪問屬性,也可以訪問方法。super.move();//父類的move} } ________________________________________________________________ public class Super{public static void main(String[] args){Vip v = new Vip("張三");v.shopping();} } class Customer {String name;public Customer(){}public Customer(String name){super();this.name = name;}public void doSome(){System.out.println(this.name + " do some!");System.out.println(name + " do some!");//錯誤: 找不到符號//System.out.println(super.name + " do some!");//Object類沒有name屬性} } class Vip extends Customer{// 假設子類也有一個同名屬性// java中允許在子類中出現和父類一樣的同名變量/同名屬性。String name; // 實例變量public Vip(){}public Vip(String name){super(name);// this.name = null;}public void shopping(){/*java是怎么來區分子類和父類的同名屬性的?this.name:當前對象的name屬性super.name:當前對象的父類型特征中的name屬性。*/System.out.println(this.name + "正在購物!"); // null 正在購物 子類的nameSystem.out.println(super.name + "正在購物!"); // 張三正在購物 父類的nameSystem.out.println(name + "正在購物!"); //null 正在購物 子類的name} }

3)super關鍵字和this關鍵字重要結論

  • 當一個構造方法第一行:既沒有this()又沒有super()的話,默認會有一個super();
    通過當前子類的構造方法調用父類的無參數構造方法。所以必須保證父類的無參數構造方法是存在的。
  • 在java語言中不管是是new什么對象,最后老祖宗的Object類的無參數構造方法一定會執行。
  • this() 和 super() 不能共存,它們都是只能出現在構造方法第一行。
  • 無論是怎樣折騰,父類的構造方法是一定會執行的。

  • this是引用。this也保存內存地址,this也指向任何對象。
  • super 不是引用。super也不保存內存地址,super也不指向任何對象。
    super 只是代表當前對象內部的那一塊父類型的特征。
public class SuperTest06 {// 實例方法public void doSome(){// SuperTest06@2f92e0f4System.out.println(this);// 輸出“引用”的時候,會自動調用引用的toString()方法。//System.out.println(this.toString());//編譯錯誤: 需要'.'//System.out.println(super);}// this和super不能使用在static靜態方法中。/*public static void doOther(){System.out.println(this);System.out.println(super.xxx);}*/// 靜態方法,主方法public static void main(String[] args){SuperTest06 st = new SuperTest06();st.doSome();} } _______________________________________________________ public class Super{public static void main(String[] args){new C();} }/* class Object{public Object(){ } } *///不寫默認繼承Object class A /*extends Object*/{public A(){//默認有super();不寫默認存在;調用Object構造方法super();System.out.println("1"); //1} }class B extends A{public B(){//默認有super();不寫默認存在;調用Object構造方法super();System.out.println("2"); //2}public B(String name){super();System.out.println("3"); // 3} }class C extends B{public C(){ // 這個是最先調用的。但是最后結束。this("zhangsan");System.out.println("4");//4}public C(String name){this(name, 20);System.out.println("5");//5}public C(String name, int age){super(name);System.out.println("6");//6} }

3.3 instanceof關鍵字

  • instanceof關鍵字,用于判斷某一個類是否繼承自另一個類,即驗證兩個類之間是否屬于父類和子類的關系。
  • instanceof關鍵字判斷后是有返回值的且返回值為boolean類型。
  • 語法格式
boolean result= child instanceof parents public class computer {//我們將computer類作為父類,將它定義為電腦public static void main(String[] args) {//在父類中寫一個主函數,來對子類進行實例化Pad ipad = new Pad();LenovoPad lenovopad = new LenovoPad();//我們來利用instanceof關鍵字判斷繼承關系System.out.println("Pad是否繼承自computer類?"+(ipad instanceof computer));//判斷Pad是否繼承自computer類System.out.println("LenovoPad是否繼承自Pad類?"+(lenovopad instanceof Pad));//判斷LenovoPad是否繼承自Pad類System.out.println("LenovoPad是否繼承自computer類?"+(lenovopad instanceof computer));//判斷LenovoPad是否繼承自computer類/*由第三條判斷可以知道,instanceof關鍵字不僅能夠判斷子類是否繼承父類,還能跨越級別進行判斷* 因此我們也可以舉例判斷這些類繼承Object類(所有類的父類)如下:*/System.out.println("LenovoPad是否繼承自Object類?"+(lenovopad instanceof Object));} }class Pad extends computer{//寫一個子類Pad繼承computer類,定義為平板電腦 }class LenovoPad extends Pad{//再寫一個子類繼承Pad類,定義為聯想平板電腦 }

4、抽象類和接口

?對于面向對象編程來說,抽象是它的一大特征之一。在Java中,可以通過兩種形式來體現OOP的抽象:接口和抽象類。這兩者有太多相似的地方,又有太多不同的地方。

4.1 抽象類

1)抽象方法

  • 是一種特殊的方法:只有聲明,而沒有具體的實現。
  • 聲明格式
abstract void fun();//使用abstract關鍵字定義修飾符

2)抽象類

  • 如果一個類含有抽象方法,則稱這個類為抽象類
  • 抽象類必須在類前用abstract關鍵字修飾。
  • 因為抽象類中含有無具體實現的方法,所以不能用抽象類創建對象。

將抽象類定義為“包含抽象方法的類” ——《JAVA編程思想》

  • 語法格式
[public] abstract class ClassName {abstract void fun();}
  • 從這里可以看出,抽象類就是為了繼承而存在的
  • 實際需求
    對于一個父類,如果它的某個方法在父類中實現出來沒有任何意義,必須根據子類的實際需求來進行不同的實現,那么就可以將這個方法聲明為abstract方法,此時這個類也就成為abstract類了。
  • 包含抽象方法的類稱為抽象類,但并不意味著抽象類中只能有抽象方法,它和普通類一樣,同樣可以擁有成員變量和普通的成員方法。
  • 與普通類的區別
    ?抽象方法必須為public或者protected(因為如果為private,則不能被子類繼承,子類便無法實現該方法),缺省情況下默認為public。
    ?抽象類不能用來創建對象;
    ?如果一個類繼承于一個抽象類,則子類必須實現父類的抽象方法。如果子類沒有實現父類的抽象方法,則必須將子類也定義為abstract類。

4.2 接口

?接口,英文稱作interface,在軟件工程中,接口泛指供別人調用的方法或者函數。從這里,我們可以體會到Java語言設計者的初衷,它是對行為的抽象。

  • 語法格式
[public] interface InterfaceName {}
  • 接口中可以含有 變量和方法
    ? 接口中的變量會被隱式地指定為public static final變量(并且只能是public static final變量,用private修飾會報編譯錯誤)
    ? 方法會被隱式地指定為public abstract方法且只能是public abstract方法(用其他關鍵字,比如private、protected、static、 final等修飾會報編譯錯誤)
    ? 接口中所有的方法不能有具體的實現,也就是說,接口中的方法必須都是抽象方法。
  • 要讓一個類遵循某組特地的接口需要使用implements關鍵字,具體格式如下
class ClassName implements Interface1,Interface2,[....]{}
  • 可以看出
    ?允許一個類實現多個特定的接口【實現多繼承】
    ?如果一個非抽象類遵循了某個接口,就必須實現該接口中的所有抽象方法。
    ?對于遵循某個接口的抽象類,可以不實現該接口中的抽象方法。

4.3 抽象類和接口的區別

1)語法層面

  • 抽象類可以提供成員方法的實現細節,而接口中只能存在public abstract 方法;
  • 抽象類中的成員變量可以是各種類型的,而接口中的成員變量只能是public static final類型的;
  • 接口中不能含有靜態代碼塊以及靜態方法,而抽象類可以有靜態代碼塊和靜態方法;
  • 一個類只能繼承一個抽象類,而一個類卻可以實現多個接口。
    ?抽象類用繼承,接口用實現

2)設計層面

  • 抽象類是對一種事物的抽象,即對類抽象,而接口是對行為的抽象。
  • 抽象類是對整個類整體進行抽象,包括屬性、行為,但是接口卻是對類局部(行為)進行抽象。
飛機和鳥是不同類的事物,但是它們都有一個共性,就是都會飛。 那么在設計的時候,可以將飛機設計為一個類Airplane,將鳥設計為一個類Bird, 但是不能將 飛行 這個特性也設計為類,因此它只是一個行為特性,并不是對一類事物的抽象描述。 此時可以將 飛行 設計為一個接口Fly,包含方法fly( ), 然后AirplaneBird分別根據自己的需要實現Fly這個接口。 然后至于有不同種類的飛機,比如戰斗機、民用飛機等直接繼承Airplane即可, 對于鳥也是類似的,不同種類的鳥直接繼承Bird類即可。從這里可以看出, 繼承是一個 "是不是"的關系,而 接口 實現則是 "有沒有"的關系。 如果一個類繼承了某個抽象類,則子類必定是抽象類的種類, 而接口實現則是有沒有、具備不具備的關系,比如鳥是否能飛(或者是否具備飛行這個特點), 能飛行則可以實現這個接口,不能飛行就不實現這個接口。
  • 對比表
    ?接口比抽象類更加嚴格,但接口是實現多繼承的方式。
參數抽象類接口
默認的方法實現它可以有默認的方法實現接口完全是抽象的。它根本不存在方法的實現
實現子類使用extends關鍵字來繼承抽象類。如果子類不是抽象類的話,它需要提供抽象類中所有聲明的方法的實現。子類使用關鍵字implements來實現接口。它需要提供接口中所有聲明的方法的實現
構造器抽象類可以有構造器接口不能有構造器
與正常Java類的區別除了你不能實例化抽象類之外,它和普通Java類沒有任何區別接口是完全不同的類型
訪問修飾符抽象方法可以有public、protected和default這些修飾符接口方法默認修飾符是public。你不可以使用其它修飾符。
main方法抽象方法可以有main方法并且我們可以運行它接口沒有main方法,因此我們不能運行它。
多繼承抽象方法可以繼承一個類和實現多個接口接口只可以繼承一個或多個其它接口
速度它比接口速度要快接口是稍微有點慢的,因為它需要時間去尋找在類中實現的方法。
添加新方法如果你往抽象類中添加新的方法,你可以給它提供默認的實現。因此你不需要改變你現在的代碼。如果你往接口中添加方法,那么你必須改變實現該接口的類。

總結

以上是生活随笔為你收集整理的Java剑开天门(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。