<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 類的繼承 #### 繼承的概念 在Java中,類的繼承是指在一個現有類的基礎上去構建一個新的類,構建出來的新類被稱作子類,現有類被稱作父類,子類會自動擁有父類所有可繼承的屬性和方法。在程序中,如果想聲明一個類繼承另一個類,需要使用extends關鍵字,接下來通過一個案例來學習子類是如何繼承父類的。 ```java // 定義動物類 class Animal { String name; void shout() { System.out.println("動物發出叫聲"); } } // 定義dog類繼承動物類 class Dog extends Animal { public void printName() { System.out.println("name = " + name); } } public class Example { public static void main(String[] args) { Dog dog = new Dog(); dog.name = "極品二哈"; dog.printName(); dog.shout(); } } ``` 運行結果: ``` name = 極品二哈 動物發出叫聲 ``` 例子中,Dog類通過extends關鍵字繼承了Animal類,這樣Dog類便是Animal類的子類。從運行結果不難看出,子類雖然沒有定義name屬性和shout()方法,但是卻能訪問這兩個成員。這就說明,子類在繼承父類的時候,會自動擁有父類所有的成員。在類的繼承中,需要注意一些問題,具體如下: - 在Java中,類只支持單繼承,不允許多重繼承,也就是說一個類只能有一個直接父類,例如下面這種情況是不合法的。 ``` class A{} class B{} class C extends A,B{} //C 類不可以同時繼承A 類和B 類 ``` - 多個類可以繼承一個父類,例如下面這種情況是允許的。 ``` class A{} class B extends A{} class C extends A{} //類B 和類C 都可以繼承類A ``` - 在Java中,多層繼承是可以的,即一個類的父類可以再去繼承另外的父類,例如C類繼承自B類,而B類又可以去繼承A 類,這時,C類也可稱作A 類的子類。下面這種情況是允許的。 ``` class A{} class B extends A{} //類B 繼承類A,類B 是類A 的子類 class C extends B{} //類C 繼承類B,類C 是類B 的子類,同時也是類A 的子類 ``` - 在Java中,子類和父類是一種相對概念,也就是說一個類是某個類父類的同時,也可以是另一個類的子類。例如上面的示例中,B類是A 類的子類,同時又是C 類的父類。 #### 重寫父類方法 在繼承關系中,子類會自動繼承父類中定義的方法,但有時在子類中需要對繼承的方法進行一些修改,即對父類的方法進行重寫。需要注意的是,在子類中重寫的方法需要和父類被重寫的方法具有相同的方法名、參數列表以及返回值類型。 例中,Dog類從Animal類繼承了shout()方法,該方法在被調用時會打印“動物發出叫聲”,這明顯不能描述一種具體動物的叫聲,Dog類對象表示犬類,發出的叫聲應該是“汪汪”。為了解決這個問題,可以在Dog類中重寫父類Animal中的shout()方法。 ```java // 定義動物類 class Animal { String name; void shout() { System.out.println("動物發出叫聲"); } } // 定義dog類繼承動物類 class Dog extends Animal { void shout() { System.out.println("汪汪汪汪"); } } public class Example { public static void main(String[] args) { Dog dog = new Dog(); dog.shout(); } } ``` 運行結果: ``` 汪汪汪汪 ``` 案例中定義了Dog類并且繼承自Animal類。在子類Dog中定義了一個shout()方法對父類的方法進行重寫。從運行結果可以看出,在調用Dog類對象的shout()方法時,只會調用子類重寫的該方法,并不會調用父類的shout()方法。 **注意:**子類重寫父類方法時,不能使用比父類中被重寫的方法更嚴格的訪問權限,如父類中的方法是public的,子類的方法就不能是private的,關于訪問權限中更多的知識,我們將在本章結尾進行詳細講解,在這里大家只要有個印象就行了。 #### super關鍵字 從上一個例子中的運行結果可以看出,當子類重寫父類的方法后,子類對象將無法訪問父類被重寫的方法,為了解決這個問題,在Java中專門提供了一個super關鍵字用于訪問父類的成員。例如訪問父類的成員變量、成員方法和構造方法。接下來分兩種情況來學習一下super關鍵字的具體用法。 - 使用super關鍵字調用父類的成員變量和成員方法。具體格式如下: ``` super.成員變量 super.成員方法([參數1,參數2…]) ``` ```java // 定義動物類 class Animal { String name = "動物"; void shout() { System.out.println("動物發出叫聲"); } } // 定義dog類繼承動物類 class Dog extends Animal { String name = "犬類"; // 重寫父類的shout方法 void shout() { super.shout(); } // 定義打印方法 void printName() { System.out.println("name = " + super.name); } } public class Example { public static void main(String[] args) { Dog dog = new Dog(); dog.shout(); dog.printName(); } } ``` 運行結果: ``` 動物發出叫聲 name = 動物 ``` 案例中,定義了一個Dog類繼承Animal類,并重寫了Animal類的shout()方法。在子類Dog 的shout()方法中使用“super.shout()”調用了父類被重寫的方法,在printName()方法中使用“super.name”訪問父類的成員變量。從運行結果可以看出,子類通過super關鍵字可以成功地訪問父類成員變量和成員方法。 - 使用super關鍵字調用父類的構造方法。具體格式如下: ``` super([參數1,參數2…]) ``` ```java // 定義動物類 class Animal { public Animal(String name) { System.out.println("我是一只 " + name); } } // 定義dog類繼承動物類 class Dog extends Animal { public Dog() { super("極品二哈"); } } public class Example { public static void main(String[] args) { Dog dog = new Dog(); } } ``` 運行結果: ``` 我是一只 極品二哈 ``` 根據前面所學的知識,在實例化Dog對象時一定會調用Dog類的構造方法。從運行結果可以看出,Dog類的構造方法被調用時父類的構造方法也被調用了。需要注意的是,通過super調用父類構造方法的代碼必須位于子類構造方法的第一行,并且只能出現一次。 在定義一個類時,如果沒有特殊需求,盡量在類中定義一個無參的構造方法,避免被繼承時出現錯誤。 ## final關鍵字 #### final關鍵字修飾類 Java中的類被final關鍵字修飾后,該類將不可以被繼承,也就是不能夠派生子類。 ```java // 定義動物類 final class Animal { } // 定義dog類繼承動物類 class Dog extends Animal { } public class Example { public static void main(String[] args) { Dog dog = new Dog(); } } ``` 編譯程序報錯 由于Animal類被final關鍵字所修飾,因此,當Dog類繼承Animal類時,編譯出現了“無法從最終Animal進行繼承”的錯誤。由此可見,被final關鍵字修飾的類為最終類,不能被其他類繼承。 #### final關鍵字修飾方法 當一個類的方法被final關鍵字修飾后,這個類的子類將不能重寫該方法。 ```java // 定義動物類 class Animal { public final void shout() { } } // 定義dog類繼承動物類 class Dog extends Animal { public final void shout() { } } public class Example { public static void main(String[] args) { Dog dog = new Dog(); } } ``` 編譯程序報錯 Dog 類重寫父類Animal中的shout()方法后,編譯報錯。這是因為Animal類的shout()方法被final所修飾。由此可見,被final關鍵字修飾的方法為最終方法,子類不能對該方法進行重寫。正是由于final的這種特性,當在父類中定義某個方法時,如果不希望被子類重寫,就可以使用final關鍵字修飾該方法。 #### final關鍵字修飾變量 Java中被final修飾的變量為常量,它只能被賦值一次,也就是說final修飾的變量一旦被賦值,其值不能改變。如果再次對該變量進行賦值,則程序會在編譯時報錯。 ```java public class Example { public static void main(String[] args) { final int num = 100; num = 4; } } ``` 編譯程序報錯 當第4行對num 賦值時,編譯報錯。原因在于變量num 被final修飾。由此可見,被final修飾的變量為常量,它只能被賦值一次,其值不可改變。 被final關鍵字修飾的變量為局部變量。 ```java class Student { final String name; public void introduce() { System.out.println("我是一名學生,我的名字叫" + name); } } public class Example { public static void main(String[] args) { Student student = new Student(); student.introduce(); } } ``` 出現了編譯錯誤,提示變量name沒有初始化。這是因為使用final關鍵字修飾成員變量時,虛擬機不會對其進行初始化。因此使用final修飾成員變量時,需要在定義變量的同時賦予一個初始值,下面將第2行代碼修改為: ``` final String name="小海綿"; //為final 關鍵字修飾的name 屬性賦值 ``` 運行結果: ``` 我是一名學生,我的名字叫小海綿 ``` ## 抽象類和接口 #### 抽象類 當定義一個類時,常常需要定義一些方法來描述該類的行為特征,但有時這些方法的實現方式是無法確定的。例如前面在定義Animal類時,shout()方法用于表示動物的叫聲,但是針對不同的動物,叫聲也是不同的,因此在shout()方法中無法準確描述動物的叫聲。 針對上面描述的情況,Java允許在定義方法時不寫方法體,不包含方法體的方法為抽象方法,抽象方法必須使用abstract關鍵字來修飾,具體示例如下:abstract void shout(); //定義抽象方法shout() 當一個類中包含了抽象方法,該類必須使用abstract關鍵字來修飾,使用abstract關鍵字修飾的類為抽象類,具體示例如下: ``` abstract void shout(); //定義抽象方法shout() ``` 當一個類中包含了抽象方法,該類必須使用abstract關鍵字來修飾,使用abstract關鍵字修飾的類為抽象類,具體示例如下: ``` //定義抽象類Animal abstract class Animal { //定義抽象方法shout() abstract int shout(); } ``` 在定義抽象類時需要注意,包含抽象方法的類必須聲明為抽象類,但抽象類可以不包含任何抽象方法,只需使用abstract關鍵字來修飾即可。另外,抽象類是不可以被實例化的,因為抽象類中有可能包含抽象方法,抽象方法是沒有方法體的,不可以被調用。如果想調用抽象類中定義的方法,則需要創建一個子類,在子類中將抽象類中的抽象方法進行實現。接下來通過一個案例來學習如何實現抽象類中的方法。 ```java // 定義抽象類animal abstract class Animal { // 定義抽象方法shout abstract void shout(); } // 定義dog類繼承抽象方法Animal class Dog extends Animal { // 實現抽象方法shout void shout() { System.out.println("汪汪汪汪"); } } public class Example { public static void main(String[] args) { Dog dog = new Dog(); dog.shout(); } } ``` 運行結果: ``` 汪汪汪汪 ``` 從運行結果可以看出,子類實現了父類的抽象方法后,可以正常進行實例化,并通過實例化對象調用方法。 #### 接口 如果一個抽象類中的所有方法都是抽象的,則可以將這個類用另外一種方式來定義,即接口。在定義接口時,需要使用interface關鍵字來聲明,具體示例如下: ``` interface Animal { int ID = 1; //定義全局常量 void breathe(); //定義抽象方法 void run(); } ``` 上面的代碼中,Animal即為一個接口。從示例中會發現抽象方法breathe()并沒有使用abstract關鍵字來修飾,這是因為接口中定義的方法和變量都包含一些默認修飾符。接口中定義的方法默認使用“publicabstract”來修飾,即抽象方法。接口中的變量默認使用“publicstaticfinal”來修飾,即全局常量。 由于接口中的方法都是抽象方法,因此不能通過實例化對象的方式來調用接口中的方法。此時需要定義一個類,并使用implements關鍵字實現接口中所有的方法。接下來通過一個案例來學習。 ```java // 定義接口animal interface Animal { int ID = 1; void breathe(); void run(); } // 定義dog實現接口Animal class Dog implements Animal { public void breathe() { System.out.println("狗在呼吸"); } public void run() { System.out.println("狗在跑"); } } public class Example { public static void main(String[] args) { Dog dog = new Dog(); dog.breathe(); dog.run(); } } ``` 運行結果: ``` 狗在呼吸 狗在跑 ``` 從運行結果可以看出,類Dog在實現了Animal接口后是可以被實例化的。 上面的例子是類與接口之間的實現關系,在程序中,還可以定義一個接口使用extends關鍵字去繼承另一個接口,接下來對上一個例子稍加修改,演示接口之間的繼承關系。 ```java //定義了Animal 接口 interface Animal { int ID = 1; // 定義全局常量 void breathe(); // 定義抽象方法breathe() void run(); // 定義抽象方法run() } // 定義了LandAnimal 接口,并繼承了Animal 接口 interface LandAnimal extends Animal { // 接口繼承接口 void liveOnland(); // 定義抽象方法liveOnLand() } // 定義Dog 類實現Animal 接口 class Dog implements LandAnimal { // 實現breathe()方法 public void breathe() { System.out.println("狗在呼吸"); } // 實現run()方法 public void run() { System.out.println("狗在跑"); } // 實現liveOnLand()方法 public void liveOnland() { // TODO Auto-generated method stub System.out.println("狗生活在陸地上"); } } public class Example { public static void main(String[] args) { Dog dog = new Dog(); // 創建Dog 類的實例對象 dog.breathe(); // 調用Dog 類的breathe()方法 dog.run(); // 調用Dog 類的run()方法 dog.liveOnland(); // 調用Dog 類的liveOnland()方法 } } ``` 運行結果: ``` 狗在呼吸 狗在跑 狗生活在陸地上 ``` 例中,定義了兩個接口,其中LandAnimal接口繼承了Animal接口,因此LandAnimal接口包含了三個抽象方法。當Dog類實現LandAnimal接口時,需要實現兩個接口中定義的三個方法。從運行結果看出,程序可以針對Dog類實例化對象并調用類中的方法。 為了加深初學者對接口的認識,接下來對接口的特點進行歸納,具體如下: - 接口中的方法都是抽象的,不能實例化對象。 - 當一個類實現接口時,如果這個類是抽象類,則實現接口中的部分方法即可,否則需要實現接口中的所有方法。 - 一個類通過implements關鍵字實現接口時,可以實現多個接口,被實現的多個接口之間要用逗號隔開。具體示例如下: ``` interface Run { 程序代碼…… } interface Fly { 程序代碼…… } class Bird implements Run,Fly { 程序代碼…… } ``` - 一個接口可以通過extends關鍵字繼承多個接口,接口之間用逗號隔開。具體示例如下: ``` interface Running { 程序代碼…… } interface Flying { 程序代碼…… } Interface Eating extends Running,Flying { 程序代碼…… } ``` - 一個類在繼承另一個類的同時還可以實現接口,此時,extends關鍵字必須位于implements關鍵字之前。具體示例如下: ``` class Dog extends Canidae implements Animal { //先繼承,再實現 程序代碼…… } ``` ## 多態 #### 多態概述 在設計一個方法時,通常希望該方法具備一定的通用性。例如要實現一個動物叫的方法,由于每種動物的叫聲是不同的,因此可以在方法中接收一個動物類型的參數,當傳入貓類對象時就發出貓類的叫聲,傳入犬類對象時就發出犬類的叫聲。在同一個方法中,這種由于參數類型不同而導致執行效果各異的現象就是多態。 在Java中為了實現多態,允許使用一個父類類型的變量來引用一個子類類型的對象,根據被引用子類對象特征的不同,得到不同的運行結果。接下來通過一個案例來演示。 ```java //定義接口Anmal interface Animal { void shout(); // 定義抽象shout()方法 } // 定義Cat 類實現Animal 接口 class Cat implements Animal { // 實現shout()方法 public void shout() { System.out.println("喵喵……"); } } // 定義Dog 類實現Animal 接口 class Dog implements Animal { // 實現shout()方法 public void shout() { System.out.println("汪汪……"); } } // 定義測試類 public class Example { public static void main(String[] args) { Animal an1 = new Cat(); // 創建Cat 對象,使用Animal 類型的變量an1 引用 Animal an2 = new Dog(); // 創建Dog 對象,使用Animal 類型的變量an2 引用 animalShout(an1); // 調用animalShout()方法,將an1 作為參數傳入 animalShout(an2); // 調用animalShout()方法,將an2 作為參數傳入 } // 定義靜態的animalShout()方法,接收一個Animal 類型的參數 public static void animalShout(Animal an) { an.shout(); // 調用實際參數的shout()方法 } } ``` 運行結果: ``` 喵喵…… 汪汪…… ``` 第25行、第26行代碼實現了父類類型變量引用不同的子類對象,當第27行、第28行代碼調用animalShout()方法時,將父類引用的兩個不同子類對象分別傳入,結果打印出了“喵喵”和“汪汪”。由此可見,多態不僅解決了方法同名的問題,而且還使程序變得更加靈活,從而有效地提高程序的可擴展性和可維護性。 #### 對象的類型轉換 在多態的學習中,涉及到將子類對象當作父類類型使用的情況,例如下面兩行代碼: ``` Animal an1=new Cat(); //將Cat 對象當作Animal 類型來使用 Animal an2=new Dog(); //將Dog 對象當作Animal 類型來使用 ``` 將子類對象當作父類使用時不需要任何顯式地聲明,需要注意的是,此時不能通過父類變量去調用子類中的某些方法,接下來通過一個案例來演示。 ```java //定義Animal 接口 interface Animal { void shout(); // 定義抽象方法shout() } // 定義Cat 類實現Animal 接口 class Cat implements Animal { // 實現抽象方法shout() public void shout() { System.out.println("喵喵……"); } // 定義sleep()方法 void sleep() { System.out.println("貓睡覺……"); } } // 定義測試類 public class Example { public static void main(String[] args) { Cat cat = new Cat(); // 創建Cat 類的實例對象 animalShout(cat); // 調用animalShout()方法,將cat 作為參數傳入 } // 定義靜態方法animalShout(),接收一個Animal 類型的參數 public static void animalShout(Animal animal) { animal.shout(); // 調用傳入參數animal 的shout()方法 animal.sleep(); // 調用傳入參數animal 的sleep()方法 } } ``` 編譯程序報錯 在main方法中,調用animalShout()方法時傳入了Cat類型的對象,而方法的參數類型為Animal類型,這便將Cat對象當作父類Animal類型使用。當編譯器檢查到第29行代碼時,發現Animal類中沒有定義sleep()方法,從而出現編譯程序報錯的錯誤信息,報告找不到sleep()方法。由于傳入的對象是Cat類型,在Cat類中定義了sleep()方法,通過Cat類型的對象調用sleep()方法是可行的,因此可以在animalShout()方法中將Animal類型的變量強轉為Cat類型。將animalShout()方法進行修改,具體代碼如下: ```java public static void animalShout(Animal animal) { Cat cat = (Cat) animal; //將animal 對象強制轉換為Cat 類型 cat.shout(); //調用cat 的shout()方法 cat.sleep(); //調用cat 的sleep()方法 } ``` 修改后再次編譯,程序沒有報錯,運行結果: ``` 喵喵…… 貓睡覺…… ``` #### Object類 在JDK中提供了一個Object類,它是所有類的父類,即每個類都直接或間接繼承自該類。先來看一個例子。 ```java //定義Animal 類 class Animal { // 定義動物叫的方法 void shout() { System.out.println("動物叫!"); } } // 定義測試類 public class Example { public static void main(String[] args) { Animal animal = new Animal(); // 創建Animal 類對象 System.out.println(animal.toString()); // 調用toString()方法并打印 } } ``` 運行結果: ``` Animal@15db9742 ``` 在例中,第13行代碼調用了Animal對象的toString()方法,雖然Animal類并沒有定義這個方法,但程序并沒有報錯。這是因為Animal默認繼承自Object類,在Object類中定義了toString()方法,在該方法中輸出了對象的基本信息。 Object類的toString()方法中的代碼具體如下: ``` getClass().getName()+"@"+Integer.toHexString(hashCode()); ``` 為了方便初學者理解上面的代碼,接下來分別對其中用到的方法進行解釋,具體如下: - getClass().getName()代表返回對象所屬類的類名,即Animal。 - hashCode()代表返回該對象的哈希值。 - Integer.toHexString(hashCode())代表將對象的哈希值用16進制表示。 其中,hashCode()是Object類中定義的一個方法,這個方法將對象的內存地址進行哈希運算,返回一個int類型的哈希值。 在實際開發中,通常希望對象的toString()方法返回的不僅僅是基本信息,而是一些特有的信息,這時重寫Object的toString()方法便可以實現。 ```java //定義Animal 類 class Animal { // 重寫Object 類的toString()方法 public String toString() { return "I am an animal"; } } // 定義測試類 public class Example { public static void main(String[] args) { Animal animal = new Animal(); // 創建Animal 對象 System.out.println(animal.toString()); // 打印animal 的toString()方法的返回值 } } ``` 運行結果: ``` I am an animal ``` 在例子的Animal類中重寫了Object類的toString()方法,當在main()方法中調用toString()方法時,就打印出了Animal類的描述信息“Iamananimal”。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看