Java基礎——五、繼承

五、繼承

簡要

1、說明

繼承(Inheritance)面向對象編程(OOP)的一個核心概念,它允許一個類(子類)繼承另一個類(父類)的屬性和方法,從而實現代碼重用和結構化組織。通過繼承,子類可以擴展父類的功能或者對父類的方法進行重寫

  1. 父類(超類、基類)
    • 父類是被繼承的類,它包含子類可以使用的屬性和方法
    • 在Java中,使用extends關鍵字來實現繼承。
  2. 子類(派生類)
    • 子類是繼承父類的類,它可以訪問父類的公共和受保護的成員(屬性和方法)
    • 子類可以添加新的屬性和方法,也可以重寫父類的方法
2、繼承的優點
  1. 代碼重用:
    • 子類可以直接使用父類中定義的屬性和方法,減少代碼的重復。
  2. 提高可維護性:
    • 由于子類和父類的結構化關系,系統更加模塊化,修改父類的方法時,子類也會自動更新,從而提高了系統的可維護性。
  3. 實現多態:
    • 繼承是實現多態(Polymorphism)的基礎,通過繼承和方法重寫,程序可以在運行時決定調用哪個類的方法。
3、繼承的實現

提供一個簡單的Java繼承示例:

//父類
class Animal{String name;public void eat(){System.out.println("This animal eat food.");}
}//子類
class Dog extend Animal{public void bark(){Sytem.out.println("The dog barks.");}public void eat(){System.out.println("The dog eats dog food.");}
}public class Main{public static void main(String[] args){Dog dog = new Dog();dog.name = "Buddy";//調用重寫的方法。dog.eat();//調用子類特有的方法。dog,bark();}
}
4、繼承的類型
  1. 單繼承:
    • 一個子類只能繼承一個父類。Java中不支持多繼承(即一個子類繼承多個父類),但是可以通過接口來實現,類似多繼承的效果。
  2. 多層繼承:
    • 一個類繼承另一個類,該類又繼承另一個類,形成繼承鏈。例如:類C繼承類B,類B繼承類A。
組合
1、組合 VS 繼承

繼承:

  • 是一種是一個(is-a)關系。例如,Dog繼承自Animal,表示Dog是一個Animal
  • 子類繼承父類的所有屬性和方法,但這也導致子類與父類之間的耦合度較高。
  • 如果子類發生變化,子類可能需要進行相應的修改。
  • 繼承層次過深可能導致代碼復雜性增加。

組合:

  • 是一種有一個(has - a)關系。例如,Car有一個Engine,表示car包含一個Engine對象。
  • 通過將一個類的實例作為成員變量引入到另一個類中,來實現類之間的協作。
  • 組合的類之間的耦合度較低,一個類的改變不會直接影響另一個類。
  • 組合更靈活,可以在運行時動態改變組合對象的行為。
2、組合的示例

假設我們有一個場景,需要定義一個交通工具(Vehicle),每種交通工具有不同的移動方式(MoveStrategy)。我們可以使用組合來實現不同交通工具的行為,而不是通過繼承。

定義接口和實現類:

package base.inheritance.assembly;/*** @author: LiHao* @program: interview* @description: 敘述組合的示例(用于對比繼承)* @Date: 2024-06-10-17:34:10* thinking:*/
interface MoveStrategy {/*** 移動對象。* <p>* 該方法定義了對象的移動行為,但沒有指定移動的方式或方向。* 具體的移動邏輯應在方法體內實現,這里沒有提供實現是因為示例的限制。** @see #move(int, int) 如果需要更精確的控制移動距離和方向,可以使用帶參數的移動方法。*/void move();
}/*** 具體的移動策略實現:開車*/
class DriveStrategy implements MoveStrategy {/*** 實現移動方法。* 該方法具體實現了車輛在道路上的行駛行為。通過打印信息來模擬車輛的移動過程。* 由于這是一個抽象類的抽象方法的具體實現,所以這里使用了@Override注解來標明此方法是對父類抽象方法的實現。*/@Overridepublic void move() {System.out.println("Driving on the road.");}
}/*** 具體的移動策略實現:飛行*/
class FiyStrategy implements MoveStrategy {@Overridepublic void move() {System.out.println("Flying in the sky.");}
}/*** 具體的移動策略實現:行走*/
class WalkStrategy implements MoveStrategy {@Overridepublic void move() {System.out.println("Walking on the ground.");}
}/*** 交通工具類*/
class Vehicle {private MoveStrategy moveStrategy;/*** 構造函數,用于初始化車輛對象。** @param moveStrategy 移動策略對象,車輛將使用該策略來進行移動。*                     通過傳入不同的移動策略,車輛可以實現不同的移動方式,*                     提供了策略模式中的策略對象。*/public Vehicle(MoveStrategy moveStrategy) {this.moveStrategy = moveStrategy;}/*** 設置移動策略。** 本方法用于更換對象的移動策略,允許對象在運行時根據需要動態調整其移動方式。* 通過傳入不同的移動策略實例,對象可以實現不同的移動行為,從而提高代碼的靈活性和可擴展性。** @param moveStrategy 移動策略對象,用于定義對象的移動行為。*/public void setMoveStrategy(MoveStrategy moveStrategy){this.moveStrategy = moveStrategy;}/*** 實現移動操作。* 通過策略模式,調用指定的移動策略來執行移動操作。* 此方法的目的是為了封裝移動行為,具體的移動方式由包含的移動策略對象決定。*/public void move() {moveStrategy.move();}/*** 使用組合來實現不同的行為* @param args*/public static void main(String[] args) {//創建不同的移動策略MoveStrategy driveStrategy = new DriveStrategy();MoveStrategy fiyStrategy = new FiyStrategy();MoveStrategy walkStrategy = new WalkStrategy();//創建交通工具并設置移動策略Vehicle car = new Vehicle(driveStrategy);car.move();//動態改變交通工具的移動策略car.setMoveStrategy(fiyStrategy);car.move();//創建另一個交通工具并設置不同的移動策略Vehicle person = new Vehicle(walkStrategy);person.move();}
}

輸出:

Driving on the road.
Flying in the sky.
Walking on the ground.
3、組合的優點
  1. 靈活性:
    • 可以在運行時動態改變對象的行為,而無需修改類的層次結構。
    • 可以通過組合不同的策略對象來實現多種行為。
  2. 低耦合:
    • 組合的類之間的耦合度較低,一個類的改變不會直接影響另一個類。
    • 更容易維護和擴展系統,添加新的策略不需要修改現有的類。
  3. 遵循單一職責原則:
    • 每一個類只需要關注一個特定的功能,職責更加準確。

通過理解和應用組合的模式,可以創建更靈活、易維護的系統,特別是在需求頻繁變化的場景下,組合模式的優勢更加明顯。

5、注意事項
  1. 訪問控制

    • 父類的private成員不能被子類直接訪問,但protectedpublic成員可以被子類訪問。
  2. 構造方法

    • 構造方法不能被繼承,但子類可以調用父類的構造方法(使用super關鍵字)。
  3. 組合優于繼承

    • 在某些情況下,使用組合(即在一個類中包含另一個類的實例)可能比繼承更合適,因為它可以提供更好的靈活性和減少耦合度。

通過理解和應用繼承,可以創建更簡潔、可維護性強且擴展性好的代碼結構,這是面向對象編程不可或缺的一部分。

訪問權限

Java 中有三個訪問權限修飾符:private、protected 以及 public

  • 如果不加訪問修飾符,表示包級可見。可以對類或類中的成員(字段和方法)加上訪問修飾符。

  • 類可見表示其它類可以用這個類創建實例對象

  • 成員可見表示其它類可以用這個類的實例對象訪問到該成員

protected 用于修飾成員,表示在繼承體系中成員對于子類可見,但是這個訪問修飾符對于類沒有意義。

設計良好的模塊會隱藏所有的實現細節,把它的 API 與它的實現清晰地隔離開來。模塊之間只通過它們的 API 進行通信,一個模塊不需要知道其他模塊的內部工作情況,這個概念被稱為信息隱藏或封裝。因此訪問權限應當盡可能地使每個類或者成員不被外界訪問

如果子類的方法重寫了父類的方法,那么子類中該方法的訪問級別不允許低于父類的訪問級別。這是為了確保可以使用父類實例的地方都可以使用子類實例去代替,也就是確保滿足里氏替換原則。

**字段決不能是公有的,因為這么做的話就失去了對這個字段修改行為的控制,客戶端可以對其隨意修改。**例如下面的例子中,AccessExample 擁有 id 公有字段,如果在某個時刻,我們想要使用 int 存儲 id 字段,那么就需要修改所有的客戶端代碼

public class AccessExample {public String id;
}

可以使用公有的 getter 和 setter 方法來替換公有字段,這樣的話就可以控制對字段的修改行為。

public class AccessExample {private int id;public String getId() {return id + "";}public void setId(String id) {this.id = Integer.valueOf(id);}
}

但是也有例外,如果是包級私有的類或者私有的嵌套類,那么直接暴露成員不會有特別大的影響。

public class AccessWithInnerClassExample {private class InnerClass {int x;}private InnerClass innerClass;public AccessWithInnerClassExample() {innerClass = new InnerClass();}public int getValue() {return innerClass.x;  // 直接訪問}
}

抽象類與接口

一、抽象類
1.定義

抽象類是不能被實例化的類,它用來作為其它類的基類。抽象類可以包含抽象方法(沒有具體的方法)和具體方法(有方法體的方法)。

抽象類為什么不能被實例化?

設計目的:

  1. 不完整的實現:抽象類是用了作為其它類型的基類的,它包含抽象方法,這些方法沒有實現。因為抽象類本身并沒有提供所有方法的實現,它不完整,所以不能被實例化。實例化一個不完整的對象是沒有意義的。

特征與語言規范:

  1. 強制子類實現:抽象類中的抽象方法定義了子類必須實現的行為,這是一種設計模式,確保所有子類都提供具體實現。如果允許實例化對抽象類,那么這些抽象方法在沒有實現的情況下就會被調用,導致錯誤。
  2. 語法和編譯器要求:在Java語言規范中,抽象類被定義為不能被實例化。如果嘗試實例化一個抽象類,編譯器會報錯。這是為了確保編譯時就能發現設計上的錯誤。

示例代碼:

abstract class Animal {abstract void makeSound(); // 抽象方法,沒有方法體void eat() {System.out.println("This animal is eating.");}
}class Dog extends Animal {@Overridevoid makeSound() {System.out.println("Bark");}
}public class Main {public static void main(String[] args) {// Animal animal = new Animal(); // 編譯錯誤:Animal是抽象的;不能實例化Dog dog = new Dog();dog.makeSound(); // 輸出:Barkdog.eat(); // 輸出:This animal is eating.}
}

在上述示例中:

  • Animal類是一個抽象類,包含一個抽象方法makeSound(),沒有方法體。
  • Dog類繼承自Animal并實現了makeSound()方法。
  • 試圖實例化Animal類會導致編譯錯誤,因為Animal是抽象的,不能直接創建其實例。

總結:

抽象類不能實例化的原因主要是:

  1. 不完整實現:抽象類本身不完整,包含未實現的方法。
  2. 設計模式:確保子類實現必要的方法,強制制定的設計模式。
  3. 語言規范:Java語言規范和編譯器的要求,防止設計錯誤。

通過這些機制,抽象類可以正確地作為其它類的基類,確保代碼的健壯性和設計的一致性。

2.關鍵字

使用abstract關鍵字類定義一個抽象類的抽象方法。

3.特點
  1. 部分實現:抽象類可以包含具體的方法實現,也可以包含抽象方法。子類可以繼承抽象類并實現未實現的方法。
  2. 構造方法:可以有構造方法,但不能實例化對象。構造方法通常被用于子類的實例化過程中調用。
  3. 字段和方法:可以包含字段和方法(即可以是抽象的也可以是具體的)。
  4. 繼承:一個類可以繼承一個抽象類(單繼承)。
  5. 訪問修飾符:可以使用各種訪問修飾符(public,protected,private)。

抽象類和抽象方法都使用 abstract 關鍵字進行聲明。如果一個類中包含抽象方法,那么這個類必須聲明為抽象類

抽象類和普通類最大的區別是:抽象類不能被實例化,只能被繼承

public abstract class AbstractClassExample {protected int x;private int y;public abstract void func1();public void func2() {System.out.println("func2");}
}
public class AbstractExtendClassExample extends AbstractClassExample {@Overridepublic void func1() {System.out.println("func1");}
}
// AbstractClassExample ac1 = new AbstractClassExample(); // 'AbstractClassExample' is abstract; cannot be instantiated
AbstractClassExample ac2 = new AbstractExtendClassExample();
ac2.func1();

2. 接口

接口是抽象類的延伸,在 Java 8 之前,它可以看成是一個完全抽象的類,也就是說它不能有任何的方法實現。

從 Java 8 開始,接口也可以擁有默認的方法實現,這是因為不支持默認方法的接口的維護成本太高了。在 Java 8 之前,如果一個接口想要添加新的方法,那么要修改所有實現了該接口的類,讓它們都實現新增的方法

接口的成員(字段 + 方法)默認都是 public 的,并且不允許定義為 private 或者 protected。從 Java 9 開始,允許將方法定義為 private,這樣就能定義某些復用的代碼又不會把方法暴露出去。

接口的字段默認都是 static 和 final 的

public interface InterfaceExample {void func1();default void func2(){System.out.println("func2");}int x = 123;// int y;               // Variable 'y' might not have been initializedpublic int z = 0;       // Modifier 'public' is redundant for interface fields// private int k = 0;   // Modifier 'private' not allowed here// protected int l = 0; // Modifier 'protected' not allowed here// private void fun3(); // Modifier 'private' not allowed here
}
public class InterfaceImplementExample implements InterfaceExample {@Overridepublic void func1() {System.out.println("func1");}
}
// InterfaceExample ie1 = new InterfaceExample(); // 'InterfaceExample' is abstract; cannot be instantiated
InterfaceExample ie2 = new InterfaceImplementExample();
ie2.func1();
System.out.println(InterfaceExample.x);

3. 比較

  • 從設計層面上看,抽象類提供了一種 IS-A 關系,需要滿足里式替換原則,即子類對象必須能夠替換掉所有父類對象。而接口更像是一種 LIKE-A 關系,它只是提供一種方法實現契約,并不要求接口和實現接口的類具有 IS-A 關系

  • 從使用上來看,一個類可以實現多個接口,但是不能繼承多個抽象類

  • 接口的字段只能是 static 和 final 類型的,而抽象類的字段沒有這種限制

  • 接口的成員只能是 public 的,而抽象類的成員可以有多種訪問權限

4. 使用選擇

使用接口:

  • 需要讓不相關的類都實現一個方法,例如不相關的類都可以實現 Comparable 接口中的 compareTo() 方法;
  • 需要使用多重繼承

使用抽象類

  • 需要在幾個相關的類中共享代碼
  • 需要能控制繼承來的成員的訪問權限,而不是都為 public。
  • 需要繼承非靜態和非常量字段

在很多情況下,接口優先于抽象類。因為接口沒有抽象類嚴格的類層次結構要求,可以靈活地為一個類添加行為。并且從 Java 8 開始,接口也可以有默認的方法實現,使得修改接口的成本也變的很低。

  • Abstract Methods and Classes(opens new window)
  • 深入理解 abstract class 和 interface(opens new window)
  • When to Use Abstract Class and Interface(opens new window)
  • Java 9 Private Methods in Interfaces(opens new window)

super

  • 訪問父類的構造函數:可以使用 super() 函數訪問父類的構造函數,從而委托父類完成一些初始化的工作。應該注意到,子類一定會調用父類的構造函數來完成初始化工作,一般是調用父類的默認構造函數,如果子類需要調用父類其它構造函數,那么就可以使用 super() 函數。
  • 訪問父類的成員:如果子類重寫了父類的某個方法,可以通過使用 super 關鍵字來引用父類的方法實現。
public class SuperExample {protected int x;protected int y;public SuperExample(int x, int y) {this.x = x;this.y = y;}public void func() {System.out.println("SuperExample.func()");}
}
public class SuperExtendExample extends SuperExample {private int z;public SuperExtendExample(int x, int y, int z) {super(x, y);this.z = z;}@Overridepublic void func() {super.func();System.out.println("SuperExtendExample.func()");}
}
SuperExample e = new SuperExtendExample(1, 2, 3);
e.func();
SuperExample.func()
SuperExtendExample.func()

Using the Keyword super

重寫與重載

1. 重寫(Override)

存在于繼承體系中,指子類實現了一個與父類在方法聲明上完全相同的一個方法。

為了滿足里式替換原則,重寫有以下三個限制:

  • 子類方法的訪問權限必須大于等于父類方法;
  • 子類方法的返回類型必須是父類方法返回類型或為其子類型。
  • 子類方法拋出的異常類型必須是父類拋出異常類型或為其子類型。

使用 @Override 注解,可以讓編譯器幫忙檢查是否滿足上面的三個限制條件。

下面的示例中,SubClass 為 SuperClass 的子類,SubClass 重寫了 SuperClass 的 func() 方法。其中:

  • 子類方法訪問權限為 public,大于父類的 protected。
  • 子類的返回類型為 ArrayList,是父類返回類型 List 的子類。
  • 子類拋出的異常類型為 Exception,是父類拋出異常 Throwable 的子類。
  • 子類重寫方法使用 @Override 注解,從而讓編譯器自動檢查是否滿足限制條件。
class SuperClass {protected List<Integer> func() throws Throwable {return new ArrayList<>();}
}class SubClass extends SuperClass {@Overridepublic ArrayList<Integer> func() throws Exception {return new ArrayList<>();}
}

在調用一個方法時:

  1. 先從本類中查找看是否有對應的方法
  2. 如果沒有再到父類中查看,看是否從父類繼承來。
  3. 否則就要對參數進行轉型,轉成父類之后看是否有對應的方法。總的來說,方法調用的優先級為:
  • this.func(this)
  • super.func(this)
  • this.func(super)
  • super.func(super)
/*A|B|C|D*/class A {public void show(A obj) {System.out.println("A.show(A)");}public void show(C obj) {System.out.println("A.show(C)");}
}class B extends A {@Overridepublic void show(A obj) {System.out.println("B.show(A)");}
}class C extends B {
}class D extends C {
}
public static void main(String[] args) {A a = new A();B b = new B();C c = new C();D d = new D();// 在 A 中存在 show(A obj),直接調用a.show(a); // A.show(A)// 在 A 中不存在 show(B obj),將 B 轉型成其父類 Aa.show(b); // A.show(A)// 在 B 中存在從 A 繼承來的 show(C obj),直接調用b.show(c); // A.show(C)// 在 B 中不存在 show(D obj),但是存在從 A 繼承來的 show(C obj),將 D 轉型成其父類 Cb.show(d); // A.show(C)// 引用的還是 B 對象,所以 ba 和 b 的調用結果一樣A ba = new B();ba.show(c); // A.show(C)ba.show(d); // A.show(C)
}

2. 重載(Overload)

存在于同一個類中,指一個方法與已經存在的方法名稱上相同,但是參數類型、個數、順序至少有一個不同

應該注意的是,返回值不同,其它都相同不算是重載

class OverloadingExample {public void show(int x) {System.out.println(x);}public void show(int x, String y) {System.out.println(x + " " + y);}
}
public static void main(String[] args) {OverloadingExample example = new OverloadingExample();example.show(1);example.show(1, "2");
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/37707.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/37707.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/37707.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于docker安裝redis服務

Redis是我們在項目中經常需要使用的緩存數據庫&#xff0c;安裝redis的方式也有很多&#xff0c;本文主要是給大家講解如何基于docker進行redis服務的安裝&#xff0c;主要介紹&#xff0c;如何拉取redis鏡像、如何掛載redis的數據以及使用redis的配置文件和開啟認證等功能&…

steam社區載入失敗、加載不出來、打不開?

隨著steam夏季大促的到來&#xff0c;最近steam在線用戶越來越多了&#xff0c;很多玩家在自己喜歡的游戲社區里看最新的玩法、攻略和玩家的游戲心得。不過有不少玩家表示有時候會打不開游戲社區或是社區加載失敗等問題。根據大家遇到的問題&#xff0c;這里總結了幾種解決方法…

構建現代醫療:互聯網醫院系統源碼與電子處方小程序開發教學

本篇文章&#xff0c;筆者將探討互聯網醫院系統的源碼結構和電子處方小程序的開發&#xff0c;幫助讀者更好地理解和掌握這些前沿技術。 一、互聯網醫院系統源碼結構 互聯網醫院系統通常由多個模塊組成&#xff0c;每個模塊負責不同的功能。以下是一個典型的互聯網醫院系統的主…

基于C語言的Jacobi迭代和Gauss-Seidel迭代的方程組求解實現

文章目錄 Jacobi迭代方法介紹Gauss-Seidel迭代方法介紹具體代碼實現示例題目實現效果 Jacobi迭代方法介紹 Jacobi迭代法是一種簡單的迭代求解方法&#xff0c;適用于嚴格對角占優矩陣。其基本思想是利用當前迭代步的已知解來更新下一個迭代步的解。在C語言實現中&#xff0c;我…

商協會小程序如何提升商協會形象?

商協會小程序在提升商協會形象方面扮演著重要角色。以下是關于商協會小程序如何提升商協會形象的一些場景分析&#xff1a; 1、數字化名片與品牌形象展示 小程序可以作為商協會的數字名片&#xff0c;通過展示商會文化、活動信息和會員服務&#xff0c;有效提升商會的品牌形象…

鏈表反轉的兩種方式

鏈表反轉的兩種方式 1.頭插法 先創建一個新的鏈表&#xff0c;然后不斷遍歷我們想要反轉的鏈表&#xff0c;再一個一個使用頭插法插入到我們新建立的鏈表中&#xff0c;這樣鏈表就倒置了。 LinkList Reverse(LinkList re) {LinkList n;n (LinkList)malloc(sizeof(LNode));n…

C語言代碼風格

程序文件的說明&#xff0c;一般放在文件頭部注釋。 用來描述文件的作用、作者、日期等信息。一般格式如下&#xff1a; /** 文件名&#xff1a;filename.c* 功能&#xff1a;簡要描述文件的功能或作用* 作者&#xff1a;作者姓名* 日期&#xff1a;創建日期或最近修改日期*/…

Textual Learning2 -- 使用時的小問題

1、出現的問題&#xff1a; 在vscode里面直接運行函數會顯示報錯&#xff1a; 我嘗試在vscode中含textual庫的環境下運行&#xff0c;但仍然報錯 2、解決方案&#xff1a; 在命令行中運行&#xff1a; 首先按winR&#xff0c;輸入cmd打開命令行 或在已經安裝的conda環境&a…

古人的智慧結晶——水銃:揭秘明清時期的消防神器

明代的《奇器圖說》是一本記錄了當時各種奇巧機械的著作&#xff0c;而水銃則是書中記載的一項令人驚嘆的發明&#xff0c;它不僅展示了古人對物理原理的深刻理解&#xff0c;更是早期消防技術的一個縮影。 水銃&#xff0c;這個名字聽起來似乎有些陌生&#xff0c;但在古代&am…

在數據庫水平擴展中,名人問題(Celebrity Problem)也被稱為熱點鍵問題(Hotspot Key Problem)。

在數據庫水平擴展中&#xff0c;名人問題&#xff08;Celebrity Problem&#xff09;也被稱為熱點鍵問題&#xff08;Hotspot Key Problem&#xff09;。這是指某些特定的鍵&#xff08;例如名人或非常受歡迎的內容&#xff09;會導致某個分片&#xff08;shard&#xff09;被過…

電腦文件kernel32.dll缺失要怎么處理?怎么才能一鍵修復kernel32.dll文件

關鍵系統文件kernel32.dll的缺失&#xff0c;這種情況不僅會導致系統運行不穩定&#xff0c;甚至可能完全無法啟動某些應用程序。kernel32.dll 是一個至關重要的動態鏈接庫文件&#xff0c;它與Windows操作系統的多個基本操作相關聯&#xff0c;包括內存管理、進程和線程的控制…

dledger原理源碼分析系列(二)-心跳

簡介 dledger是openmessaging的一個組件&#xff0c; raft算法實現&#xff0c;用于分布式日志&#xff0c;本系列分析dledger如何實現raft概念&#xff0c;以及dledger在rocketmq的應用 本系列使用dledger v0.40 本文分析dledger的心跳 關鍵詞 Raft Openmessaging 心跳/…

C++中的常成員函數

2024年6月29日&#xff0c;周日下午 例如&#xff0c;以下是一個常成員函數的示例&#xff1a; class MyClass { public:int getValue() const {return value;} private:int value; };常成員函數是C中一種特殊的成員函數&#xff0c;它具有以下特點&#xff1a; 不可修改對象…

Flink Window DEMO 學習

該文檔演示了fink windows的操作DEMO 環境準備&#xff1a; kafka本地運行&#xff1a;kafka部署自動生成名字代碼&#xff1a;隨機名自動生成隨機IP代碼&#xff1a;隨機IPFlink 1.18 測試數據 自動向kafka推送數據 import cn.hutool.core.date.DateUtil; import com.alibab…

技術賦能教育:校園3D電子地圖與AR導航解決方案

隨著高考的落幕&#xff0c;又一批新鮮血液即將注入大學校園。面對陌生的環境&#xff0c;如何快速適應、準確找到目標地點&#xff0c;成為新生們的一大難題。同時&#xff0c;對于學校而言&#xff0c;如何向報考人員直觀展示校園環境&#xff0c;提供沉浸式參觀體驗&#xf…

Mybatis-Plus學習|快速入門CRUD、主鍵生成策略(雪花算法、主鍵自增等)、自動填充、樂觀鎖、分頁插件、邏輯刪除

MyBatisPlus概述 為什么要學習它呢?MyBatisPlus可以節省我們大量工作時間&#xff0c;所有的CRUD代碼它都可以自動化完成! JPA、tk-mapper、MyBatisPlus 偷懶的! MyBatis-Plus(簡稱 MP)是一個 MyBatis 的增強工具&#xff0c;在 MyBatis 的基礎上只做增強不做改變&#xff…

Pytorch學習之torch.nn.functional.pad()函數

PyTorch學習之torch.nn.functional.pad函數 一、簡介 torch.nn.functional.pad 是 PyTorch 中用于對張量進行填充操作的函數。填充操作在處理圖像、序列數據等任務時非常常見&#xff0c;它可以在張量的指定維度兩端添加一定數量的元素&#xff0c;填充方式多樣&#xff0c;包…

Git的基本使用方法

Git的基本使用方法 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們將深入探討Git的基本使用方法&#xff0c;Git作為目前最流行的版本控制系統之一&…

Day 48 消息隊列集群RabbitMQ

消息隊列集群-RabbitMQ 一、消息中間件 中間件 tomcat java web中間件 web容器 mysql php php mysql uwsgi python mysql mycat 數據庫中間件 rabbitMQ 消息中間件 1、簡介 MQ 全稱為&#xff08;Message Queue消息隊列&#xff09;。是一種應用程序對應用程序的通信方…

【全球首個開源AI數字人】DUIX數字人-打造你的AI伴侶!

目錄 1. 引言1.1 數字人技術的發展背景1.2 DUIX數字人項目的開源意義1.3 DUIX數字人技術的獨特價值1.4 本文目的與結構 2. DUIX數字人概述2.1 定義與核心概念2.2 硅基智能與DUIX的關系2.3 技術架構2.4 開源優勢2.5 應用場景2.6 安全與合規性 3. DUIX數字人技術特點3.1 開源性與…