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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

详细分析如何在java代码中使用继承和组合

發布時間:2025/1/21 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详细分析如何在java代码中使用继承和组合 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 繼承與組合
      • 何時在Java中使用繼承
      • 何時在Java中使用組合
      • 繼承與組成:兩個例子
      • 用Java繼承重寫方法
      • Java不具有多重繼承
      • 使用super訪問父類方法
      • 構造函數與繼承一起使用
      • 類型轉換和ClassCastException
      • 用超類型進行轉換
      • 查看例子分析執行結果

繼承與組合


繼承和組合是程序員用在類和對象之間建立關系的兩種編程技術。繼承是從另一類繼承一個類,而組合將一個類定義為其部分的總和。

通過繼承創建的類和對象是強耦合,因為在繼承關系中更改父類或超類可能會破壞代碼。通過組合創建的類和對象是松耦合,這意味著可以更輕松地更改組件,而無需破壞代碼。

因此組合提供了更大的靈活性,所以許多程序員已經知道,組合是比繼承更好的選擇。

繼承與組合之間的區別,以及如何選擇使用繼承和組合。請繼續下面干貨。

何時在Java中使用繼承

在面向對象的編程中,當我們知道孩子與其父母之間存在“是”關系時,就可以使用繼承。一些示例是:

  • 貓是動物。
  • 汽車是車輛。
    在這種情況下,子類或子類都是父類或超類的專門版本。從超類繼承是代碼重用的一個示例。為了更好地理解這種關系,請看下面例子:
class Vehicle {String brand;String color;double weight;double speed;void move() {System.out.println("The vehicle is moving");}}public class Car extends Vehicle {String licensePlateNumber;String owner;String bodyStyle;public static void main(String... inheritanceExample) {System.out.println(new Vehicle().brand);System.out.println(new Car().brand);new Car().move();}}

在考慮使用繼承時,子類是否確實是超類的更專門的版本。在這種情況下,汽車是車輛的一種,因此繼承關系很有意義。

何時在Java中使用組合

在面向對象的編程中,我們可以在一個對象“具有”另一個對象(或屬于另一個對象)的情況下使用組合。一些示例是:

  • 汽車有電池(電池是汽車的一部分)。
  • 一個人有心臟(心臟是一個人的一部分)。
  • 房子有一個客廳(客廳是房子的一部分)。
    為了更好地理解這種類型的關系,請看下面例子:
public class CompositionExample {public static void main(String... houseComposition) {new House(new Bedroom(), new LivingRoom());}static class House {Bedroom bedroom;LivingRoom livingRoom;House(Bedroom bedroom, LivingRoom livingRoom) {this.bedroom = bedroom;this.livingRoom = livingRoom;}}static class Bedroom { }static class LivingRoom { }}

在這種情況下,我們知道一所房子有一個客廳和一間臥室,因此我們可以使用Bedroom和 LivingRoom對象構成一個House。

繼承與組成:兩個例子

看下面的代碼。這是繼承的好例子嗎?

import java.util.HashSet;public class CharacterBadExampleInheritance extends HashSet<Object> {public static void main(String... badExampleOfInheritance) {BadExampleInheritance badExampleInheritance = new BadExampleInheritance();badExampleInheritance.add("Homer");badExampleInheritance.forEach(System.out::println);}

在這種情況下,子類繼承了許多它永遠不會使用的方法,導致緊耦合的代碼既混亂又難以維護。

現在,讓我們使用組合代碼重寫上面例子:

import java.util.HashSet; import java.util.Set;public class CharacterCompositionExample {static Set<String> set = new HashSet<>();public static void main(String... goodExampleOfComposition) {set.add("Homer");set.forEach(System.out::println);}

在這種情況下使用組合允許 CharacterCompositionExample類僅使用的兩個HashSet方法,而無需繼承所有方法。這樣可以簡化代碼,減少耦合,從而更易于理解和維護。

用Java繼承重寫方法

繼承使我們可以在新類中重用一個類的方法和其他屬性,這非常方便。但是要使繼承真正起作用,我們還需要能夠在新的子類中更改某些繼承的行為。請看具體例子:

class Animal {void emitSound() {System.out.println("The animal emitted a sound");}}class Cat extends Animal {@Overridevoid emitSound() {System.out.println("Meow");} }class Dog extends Animal { }public class Main {public static void main(String... doYourBest) {Animal cat = new Cat(); // MeowAnimal dog = new Dog(); // The animal emitted a soundAnimal animal = new Animal(); // The animal emitted a soundcat.emitSound();dog.emitSound();animal.emitSound();}}

以上例子是方法覆蓋的Java繼承。首先,我們擴展Animal類創建一個新的Cat類。接下來,我們覆蓋Animal類的emitSound()方法來獲取Cat特定聲音。即使我們將類類型聲明為Animal,當我們實例化Cat時也會得到貓的叫聲。 方法重載是多態。

Java不具有多重繼承

與某些語言(例如C ++)不同,Java不允許對類進行多重繼承。但是,可以使用逐一繼承或實現多個接口。
下面例子使用java多重繼承,則代碼將無法編譯:

class Animal {} class Mammal {} class Dog extends Animal, Mammal {}

1、使用類逐一繼承:

class Animal {} class Mammal extends Animal {} class Dog extends Mammal {}

2、使用接口

interface Animal {} interface Mammal {} class Dog implements Animal, Mammal {}

使用super訪問父類方法

當兩個類通過繼承相關聯時,子類必須能夠訪問其父類的每個可訪問字段,方法或構造函數。在Java中,我們使用保留字super來確保子類仍然可以訪問其父類的重寫方法:

public class SuperWordExample {class Character {Character() {System.out.println("A Character has been created");}void move() {System.out.println("Character walking...");}}class Moe extends Character {Moe() {super();}void giveBeer() {super.move();System.out.println("Give beer");}}}

在此示例中,Character是Moe的父類。在子類中使用super,我們可以訪問Character的 move()方法。

構造函數與繼承一起使用

當一個類繼承自另一個類時,在加載其子類之前,始終會先加載超類的構造函數。在大多數情況下,保留字super將自動添加到構造函數中。但是,如果超類在其構造函數中有一個參數,我們將手動調用該super構造函數,如下所示:

public class ConstructorSuper {class Character {Character() {System.out.println("The super constructor was invoked");}}class Barney extends Character {// No need to declare the constructor or to invoke the super constructor// The JVM will to that}}

如果父類的構造函數帶有至少一個參數,則必須在子類中聲明該構造函數,并使用super它顯式調用父構造函數。super保留字不會被自動添加,沒有它的代碼將無法編譯。例如:

public class CustomizedConstructorSuper {class Character {Character(String name) {System.out.println(name + "was invoked");}}class Barney extends Character {// We will have compilation error if we don't invoke the constructor explicitly// We need to add itBarney() {super("Barney Gumble");}}}

類型轉換和ClassCastException

強制轉換是一種向編譯器明確傳達確實要轉換給定類型的方式。 如果您強制轉換的類與聲明的類類型不兼容,就會產生ClassCastException。

在繼承中,我們可以在不強制轉換的情況下將子類轉換成父類,但是在不使用強制轉換的情況下不能將父類轉換成子類。

public class CastingExample {public static void main(String... castingExample) {Animal animal = new Animal();Dog dogAnimal = (Dog) animal; // We will get ClassCastExceptionDog dog = new Dog();Animal dogWithAnimalType = new Dog();Dog specificDog = (Dog) dogWithAnimalType;specificDog.bark();Animal anotherDog = dog; // It's fine here, no need for castingSystem.out.println(((Dog)anotherDog)); // This is another way to cast the object}}class Animal { } class Dog extends Animal { void bark() { System.out.println("Au au"); } }

當我們將Animal實例強制轉換為Dog,會出現類型轉換異常。這是因為Animal不知道轉換成什,它可能是貓,鳥等。沒有關于特定動物的信息。

Animal animal = new Animal();

然后做如下轉換:

Dog dogAnimal = (Dog) animal;

由于沒有Dog實例,因此無法將Animal轉換為Dog。所以會報ClassCastException。
因此應該這樣實例化Dog:

Dog dog = new Dog();

然后賦值給Animal:

Animal anotherDog = dog;

用超類型進行轉換

可以使用超類型聲明 Animal,但是如果我們要調用子類特定方法,則需要對其進行強制轉換。例如,如果我們想調用子類bark()方法怎么辦,但超類Animal不知道什么什么情況下,可以調用。請看下面例子:

Animal dogWithAnimalType = new Dog(); Dog specificDog = (Dog) dogWithAnimalType; specificDog.bark();

如果不想聲明另一個變量時,也可以使用以下情況強制轉換。

System.out.println(((Dog)anotherDog)); // This is another way to cast the object

查看例子分析執行結果

public class InheritanceCompositionChallenge {private static int result;public static void main(String... doYourBest) {Character homer = new Homer();homer.drink();new Character().drink();((Homer)homer).strangleBart();Character character = new Character();System.out.println(result);((Homer)character).strangleBart();}static class Character {Character() {result++;}void drink() {System.out.println("Drink");}}static class Homer extends Character {Lung lung = new Lung();void strangleBart() {System.out.println("Why you little!");}void drink() {System.out.println("Drink beer");lung.damageLungs();}}static class Lung {void damageLungs() {System.out.println("Soon you will need a transplant");}}}

運行main方法后輸出是什么

A)

Drink Drink Why you little! 2 Exception in thread "main" java.lang.ClassCastException:....

B)

Drink beer Soon you will need a transplant Drink Why you little! Exception in thread "main" java.lang.ClassCastException:....

C)

Drink beer Soon you will need a transplant Drink Why you little! 3 Exception in thread "main" java.lang.ClassCastException:....

D)

Drink beer Soon you will need a transplant Drink Why you little! 2 Why you little!

正確答案是C
分析代碼原因如下:

Character homer = new Homer();homer.drink();

Homer實例化對象,執行Homer方法實現,打印結果:

Drink beer Soon you will need a transplant

然后,Character類中調用drink()。

new Character().drink();

打印結果為:

Drink beer

接著我們使用強制轉換并調用strangleBart():

((Homer)homer).strangleBart();

打印結果為:

System.out.println(result);

因為super構造函數每次new對象都被調用,所以我們只需要計算Character或Homer實例化幾次。
打印結果為:3

最后,我們調用類型轉換:

((Homer) character).strangleBart();

因為我們要把父類轉換為子類,就好像要把動物轉換為鳥,因為會報ClassCastException異常。

總結

以上是生活随笔為你收集整理的详细分析如何在java代码中使用继承和组合的全部內容,希望文章能夠幫你解決所遇到的問題。

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