JAVA基礎——面向對象三大特性:封裝、繼承、多態

来源:http://www.cnblogs.com/hysum/archive/2017/07/01/7100874.html
-Advertisement-
Play Games

JAVA面向對象三大特性詳解 一、封裝 1、概念: 將類的某些信息隱藏在類內部,不允許外部程式直接訪問,而是通過該類提供的方法來實現對隱藏信息的操作和訪問。 2、好處: 只能通過規定的方法訪問數據。 隱藏類的實例細節,方便修改和實現。 3、封裝的實現步驟 需要註意:對封裝的屬性不一定要通過get/s ...


JAVA面向對象三大特性詳解



一、封裝

  1、概念:

    將類的某些信息隱藏在類內部,不允許外部程式直接訪問,而是通過該類提供的方法來實現對隱藏信息的操作和訪問。

  2、好處:

  •    只能通過規定的方法訪問數據。
  •       隱藏類的實例細節,方便修改和實現。 

  3、封裝的實現步驟

     

    需要註意:對封裝的屬性不一定要通過get/set方法,其他方法也可以對封裝的屬性進行操作。當然最好使用get/set方法,比較標準。

A、訪問修飾符

 

    從表格可以看出從上到下封裝性越來越差

B、this關鍵字

 1.this關鍵字代表當前對象

  this.屬性 操作當前對象的屬性

  this.方法 調用當前對象的方法。

 2.封裝對象的屬性的時候,經常會使用this關鍵字。

 3.當getter和setter函數參數名和成員函數名重合的時候,可以使用this區別。如:

  

C、Java 中的內部類

 內部類( Inner Class )就是定義在另外一個類裡面的類。與之對應,包含內部類的類被稱為外部類。

 那麼問題來了:那為什麼要將一個類定義在另一個類裡面呢?清清爽爽的獨立的一個類多好啊!!

 答:內部類的主要作用如下:

  1. 內部類提供了更好的封裝,可以把內部類隱藏在外部類之內,不允許同一個包中的其他類訪問該類。

  2. 內部類的方法可以直接訪問外部類的所有數據,包括私有的數據

  3. 內部類所實現的功能使用外部類同樣可以實現,只是有時使用內部類更方便。

  內部類可分為以下幾種: 

    • 成員內部類
    • 靜態內部類
    • 方法內部類
    • 匿名內部類  

  各個內部類的具體使用請轉移到另一篇隨文:http://www.cnblogs.com/hysum/p/7101974.html


二、繼承

1、繼承的概念

 繼承是類與類的一種關係,是一種“is a”的關係。比如“狗”繼承“動物”,這裡動物類是狗類的父類或者基類,狗類是動物類的子類或者派生類。如下圖所示:

   

 註:java中的繼承是單繼承,即一個類只有一個父類。

2、繼承的好處

 子類擁有父類的所有屬性和方法(除了private修飾的屬性不能擁有)從而實現了實現代碼的復用; 

3、語法規則,只要在子類加上extends關鍵字繼承相應的父類就可以了:

  

A、方法的重寫

 子類如果對繼承的父類的方法不滿意(不適合),可以自己編寫繼承的方法,這種方式就稱為方法的重寫。當調用方法時會優先調用子類的方法。

 重寫要註意:

     a、返回值類型

  b、方法名

  c、參數類型及個數

 都要與父類繼承的方法相同,才叫方法的重寫。

 重載和重寫的區別:

  方法重載:在同一個類中處理不同數據的多個相同方法名的多態手段。

  方法重寫:相對繼承而言,子類中對父類已經存在的方法進行區別化的修改。

B、繼承的初始化順序

  1、初始化父類再初始化子類

  2、先執行初始化對象中屬性,再執行構造方法中的初始化。

 基於上面兩點,我們就知道實例化一個子類,java程式的執行順序是:

 父類對象屬性初始化---->父類對象構造方法---->子類對象屬性初始化--->子類對象構造方法   

 下麵有個形象的圖:

   

C、final關鍵字

 使用final關鍵字做標識有“最終的”含義。

  1. final 修飾,則該類不允許被繼承。

  2. final 修飾方法,則該方法不允許被覆蓋(重寫)

  3. final 修飾屬性,則該類的該屬性不會進行隱式的初始化,所以 該final 屬性的初始化屬性必須有值,或在構造方法中賦值(但只能選其一,且必須選其一,因為沒有預設值!),且初始化之後就不能改了,只能賦值一次

  4. final 修飾變數,則該變數的值只能賦一次值,在聲明變數的時候才能賦值,即變為常量

D、super關鍵字

 在對象的內部使用,可以代表父類對象

  1、訪問父類的屬性:super.age

   2、訪問父類的方法:super.eat()

 super的應用:

 首先我們知道子類的構造的過程當中必須調用父類的構造方法。其實這個過程已經隱式地使用了我們的super關鍵字。

 這是因為如果子類的構造方法中沒有顯示調用父類的構造方法,則系統預設調用父類無參的構造方法。

 那麼如果自己用super關鍵字在子類里調用父類的構造方法,則必須在子類的構造方法中的第一行

 要註意的是:如果子類構造方法中既沒有顯示調用父類的構造方法,而父類沒有無參的構造方法,則編譯出錯。

(補充說明,雖然沒有顯示聲明父類的無參的構造方法,系統會自動預設生成一個無參構造方法,但是,如果你聲明瞭一個有參的構造方法,而沒有聲明無參的構造方法,這時系統不會動預設生成一個無參構造方法,此時稱為父類有沒有無參的構造方法。)

E、Object類

 Object類是所有類的父類,如果一個類沒有使用extends關鍵字明確標識繼承另一個類,那麼這個類預設繼承Object類。

 Object類中的方法,適合所有子類!!!

 那麼Object類中有什麼主要的方法呢?

 1、toString()

  a. 在Object類裡面定義toString()方法的時候返回的對象的哈希code碼(對象地址字元串)。

  我們可以發現,如果我們直接用System.out.print(對象)輸出一個對象,則運行結果輸出的是對象的對象地址字元串,也稱為哈希code碼。如:

  哈希碼是通過哈希演算法生成的一個字元串,它是用來唯一區分我們對象的地址碼,就像我們的身份證一樣。  

  b. 可以通過重寫toString()方法表示出對象的屬性

   如果我們希望輸出一個對象的時候,不是它的哈希碼,而是它的各個屬性值,那我們可以通過重寫toString()方法表示出對象的屬性。

  2、equals()

  a、equals()----返回值是布爾類型。

  b、預設的情況下,比較的是對象的引用是否指向同一塊記憶體地址-------對象實例化時,即給對象分配記憶體空間,該記憶體空間的地址就是記憶體地址。使用方法如:dog.equals(dog2);

  c、 如果是兩個對象,但想判斷兩個對象的屬性是否相同,則重寫equals()方法。

 以Dog類為例,重寫後的equals()方法如下(當然你可以根據自己想比較的屬性來重寫,這裡我以age屬性是否相同來重寫equals()方法):

    

 上面有四個判斷,它們的含義分別是:

  1.判斷地址是否相同----if (this == obj),相同則返回true

  2.判斷對象是否為空----if (obj == null),為空則返回false

  3.getClass()可以得到類對象,判斷類型是否一樣-----if (getClass() != obj.getClass()),不一樣則返回false

  4.判斷屬性值是否一樣----if (age != other.age),不一樣返回false

  5.如果地址相同,對象不為空,類型一樣,屬性值一樣則返回true

 這裡要註意的是,理解obj.getClass()得到的類對象和類的對象的區別,以下用圖形表示:
      

 可以看到,對於類對象我們關心它屬於哪個類,擁有什麼屬性和方法,比如我和你都是屬於“人”這個類對象;而類的對象則是一個類的實例化的具體的一個對象。比如我和你是兩個不同的人。


三、多態

 面向對象的最後一個特性就是多態,那麼什麼是多態呢?多態就是對象的多種形態。

 java里的多態主要表現在兩個方面:

 1.引用多態   

  父類的引用可以指向本類的對象

  父類的引用可以指向子類的對象

  這兩句話是什麼意思呢,讓我們用代碼來體驗一下,首先我們創建一個父類Animal和一個子類Dog,在主函數里如下所示:

  

  註意:我們不能使用一個子類的引用來指向父類的對象,如:

  這裡我們必須深刻理解引用多態的意義,才能更好記憶這種多態的特性。為什麼子類的引用不能用來指向父類的對象呢?我在這裡通俗給大家講解一下:就以上面的例子來說,我們能說“狗是一種動物”,但是不能說“動物是一種狗”,狗和動物是父類和子類的繼承關係,它們的從屬是不能顛倒的。當父類的引用指向子類的對象時,該對象將只是看成一種特殊的父類(裡面有重寫的方法和屬性),反之,一個子類的引用來指向父類的對象是不可行的!!

 2.方法多態

  根據上述創建的兩個對象:本類對象和子類對象,同樣都是父類的引用,當我們指向不同的對象時,它們調用的方法也是多態的。

  創建本類對象時,調用的方法為本類方法

  創建子類對象時,調用的方法為子類重寫的方法或者繼承的方法

  使用多態的時候要註意如果我們在子類中編寫一個獨有的方法(沒有繼承父類的方法),此時就不能通過父類的引用創建的子類對象來調用該方法!!!

  註意: 繼承是多態的基礎。

A、引用類型轉換 

 瞭解了多態的含義後,我們在日常使用多態的特性時經常需要進行引用類型轉換。

 引用類型轉換:

  1. 向上類型轉換(隱式/自動類型轉換),是小類型轉換到大類型。

  就以上述的父類Animal和一個子類Dog來說明,當父類的引用可以指向子類的對象時,就是向上類型轉換。如:

   

   2. 向下類型轉換(強制類型轉換),是大類型轉換到小類型(有風險,可能出現數據溢出)。

  將上述代碼再加上一行,我們再次將父類轉換為子類引用,那麼會出現錯誤,編譯器不允許我們直接這麼做雖然我們知道這個父類引用指向的就是子類對象,但是編譯器認為這種轉換是存在風險的如:

    

  那麼我們該怎麼解決這個問題呢,我們可以在animal前加上(Dog)來強制類型轉換。如:

  但是如果父類引用沒有指向該子類的對象,則不能向下類型轉換,雖然編譯器不會報錯,但是運行的時候程式會出錯,如:

  其實這就是上面所說的子類的引用指向父類的對象,而強制轉換類型也不能轉換!!

  還有一種情況是父類的引用指向其他子類的對象,則不能通過強制轉為該子類的對象。如:

    

  這是因為我們在編譯的時候進行了強制類型轉換,編譯時的類型是我們強制轉換的類型,所以編譯器不會報錯,而當我們運行的時候,程式給animal開闢的是Dog類型的記憶體空間,這與Cat類型記憶體空間不匹配,所以無法正常轉換。這兩種情況出錯的本質是一樣的,所以我們在使用強制類型轉換的時候要特別註意這兩種錯誤!!下麵有個更安全的方式來實現向下類型轉換。。。。

     3. instanceof運算符,來解決引用對象的類型,避免類型轉換的安全性問題。

  instanceof是Java的一個二元操作符,和==,>,<是同一類東東。由於它是由字母組成的,所以也是Java的保留關鍵字。它的作用是測試它左邊的對象是否是它右邊的類的實例,返回boolean類型的數據。

  我們來使用instanceof運算符來規避上面的錯誤,代碼修改如下:

  

  利用if語句和instanceof運算符來判斷兩個對象的類型是否一致。

  補充說明:在比較一個對象是否和另一個對象屬於同一個類實例的時候,我們通常可以採用instanceof和getClass兩種方法通過兩者是否相等來判斷,但是兩者在判斷上面是有差別的。Instanceof進行類型檢查規則是:你屬於該類嗎?或者你屬於該類的派生類嗎?而通過getClass獲得類型信息採用==來進行檢查是否相等的操作是嚴格的判斷,不會存在繼承方面的考慮

  總結:在寫程式的時候,如果要進行類型轉換,我們最好使用instanceof運算符來判斷它左邊的對象是否是它右邊的類的實例,再進行強制轉換。

B、抽象類

 定義:抽象類前使用abstract關鍵字修飾,則該類為抽象類。

 使用抽象類要註意以下幾點:

  1. 抽象類是約束子類必須有什麼方法,而並不關註子類如何實現這些方法。

  2. 抽象類應用場景:

   a. 在某些情況下,某個父類只是知道其子類應該包含怎樣的方法,但無法準確知道這些子類如何實現這些方法(可實現動態多態)。

   b. 從多個具有相同特征的類中抽象出一個抽象類,以這個抽象類作為子類的模板,從而避免子類設計的隨意性。

  3. 抽象類定義抽象方法只有聲明,不需要實現。抽象方法沒有方法體以分號結束,抽象方法必須用abstract關鍵字來修飾。如:

   

  4、包含抽象方法的類是抽象類。抽象類中可以包含普通的方法,也可以沒有抽象方法。如:

    

  5、抽象類不能直接創建,可以定義引用變數來指向子類對象,來實現抽象方法。以上述的Telephone抽象類為例:     

1 public abstract class Telephone {
2     public abstract void call();//抽象方法,方法體以分號結束,只有聲明,不需要實現
3     public void message(){
4         System.out.println("我是抽象類的普通方法");
5     }//抽象類中包含普通的方法
6 }
1 public class Phone extends Telephone {
2 
3     public void call() {//繼承抽象類的子類必須重寫抽象方法
4         // TODO Auto-generated method stub
5         System.out.println("我重寫了抽象類的方法");
6     }
7     
8 }

 以上是Telephone抽象類和子類Phone的定義,下麵我們看main函數里:

    

    運行結果(排錯之後):

    

C、介面

 1、概念

  介面可以理解為一種特殊的類,由全局常量和公共的抽象方法所組成。也可理解為一個特殊的抽象類,因為它含有抽象方法。

   如果說類是一種具體實現體,而介面定義了某一批類所需要遵守的規範,介面不關心這些類的內部數據,也不關心這些類里方法的實現細節,它只規定這些類里必須提供的某些方法。(這裡與抽象類相似)

 2.介面定義的基本語法

      [修飾符] [abstract] interface 介面名 [extends父介面1,2....](多繼承){

        0…n常量 (public static final)                                          

        0…n 抽象方法(public abstract)                                      

      }                                                                                             

  其中[ ]里的內容表示可選項,可以寫也可以不寫;介面中的屬性都是常量,即使定義時不添加public static final 修飾符,系統也會自動加上;介面中的方法都是抽象方法,即使定義時不添加public abstract修飾符,系統也會自動加上。

 3.使用介面

  一個類可以實現一個或多個介面,實現介面使用implements關鍵字。java中一個類只能繼承一個父類,是不夠靈活的,通過實現多個介面可以補充。

  繼承父類實現介面的語法為:

     [修飾符] class 類名 extends 父類 implements 介面1,介面2...{

       類體部分//如果繼承了抽象類,需要實現繼承的抽象方法;要實現介面中的抽象方法

     }

  註意:如果要繼承父類,繼承父類必須在實現介面之前,即extends關鍵字必須在implements關鍵字前

  補充說明:通常我們在命名一個介面時,經常以I開頭,用來區分普通的類。如:IPlayGame

  以下我們來補充在上述抽象類中的例子,我們之前已經定義了一個抽象類Telephone和子類Phone,這裡我們再創建一個IPlayGame的介面,然後在原來定義的兩個類稍作修改,代碼如下:

1 public interface IPlayGame {
2     public void paly();//abstract 關鍵字可以省略,系統會自動加上
3     public String name="游戲名字";//static final關鍵字可以省略,系統會自動加上
4 }
 1 public class Phone extends Telephone implements IPlayGame{
 2 
 3     public void call() {//繼承抽象類的子類必須重寫抽象方法
 4         // TODO Auto-generated method stub
 5         System.out.println("我重寫了抽象類的方法");
 6     }
 7 
 8     @Override
 9     public void paly() {
10         // TODO Auto-generated method stub
11         System.out.println("我重寫了介面的方法");
12     }
13     
14 }
 1 public class train {
 2     
 3 
 4     public static void main(String[] args) {
 5         // TODO Auto-generated method stub
 6         IPlayGame i=new Phone();//用介面的引用指向子類的對象
 7         i.paly();//調用介面的方法
 8         System.out.println(i.name);//輸出介面的常量
 9     
10         
11 
12 }
13 }

 運行結果:

    

 4.介面和匿名內部類配合使用

  介面在使用過程中還經常和匿名內部類配合使用。匿名內部類就是沒有沒名字的內部類,多用於關註實現而不關註實現類的名稱。

  語法格式:

1 Interface i =new interface(){
2     Public void method{
3         System.out.println(“利用匿名內部類實現介面1”);
4 }
5 };
6 i.method();

  還有一種寫法:(直接把方法的調用寫在匿名內部類的最後

1 Interface i =new interface(){
2 Public void method{
3         System.out.println(“利用匿名內部類實現介面1”);
4 }
5 }.method();

四、抽象類和介面的區別

   我們在多態的學習過程中認識到抽象類和介面都是實現java多態特性的關鍵部分,兩者都包含抽象方法,只關註方法的聲明而不關註方法的具體實現,那麼這兩者又有什麼區別呢??我們在編寫java程式的時候又該如何抉擇呢?

  參考博文:http://www.cnblogs.com/felixzh/p/5938544.html

(1)語法層面上的區別

 1.一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。
 2.抽象類中的成員變數可以是各種類型的,而介面中的成員變數只能是public static final類型的;且必須給其初值,所以實現類中不能重新定義,也不能改變其值;抽象類中的變數預設是 friendly 型,其值可以在子類中重新定義,也可以重新賦值。
 3.抽象類中可以有非抽象方法,介面中則不能有非抽象方法。
 4.介面可以省略abstract 關鍵字,抽象類不能。
 5.介面中不能含有靜態代碼塊以及靜態方法,而抽象類可以有靜態代碼塊和靜態方法;

(2)設計層面上的區別

  1)抽象類是對一種事物的抽象,即對類抽象,而介面是對行為的抽象。抽象類是對整個類整體進行抽象,包括屬性、行為,但是介面卻是對類局部(行為)進行抽象。舉個簡單的例子,飛機和鳥是不同類的事物,但是它們都有一個共性,就是都會飛。那麼在設計的時候,可以將飛機設計為一個類Airplane,將鳥設計為一個類Bird,但是不能將 飛行 這個特性也設計為類,因此它只是一個行為特性,並不是對一類事物的抽象描述。此時可以將 飛行 設計為一個介面Fly,包含方法fly( ),然後Airplane和Bird分別根據自己的需要實現Fly這個介面。然後至於有不同種類的飛機,比如戰鬥機、民用飛機等直接繼承Airplane即可,對於鳥也是類似的,不同種類的鳥直接繼承Bird類即可。從這裡可以看出,繼承是一個 "是不是"的關係,而 介面 實現則是 "有沒有"的關係。如果一個類繼承了某個抽象類,則子類必定是抽象類的種類,而介面實現則是有沒有、具備不具備的關係,比如鳥是否能飛(或者是否具備飛行這個特點),能飛行則可以實現這個介面,不能飛行就不實現這個介面。

  2)設計層面不同,抽象類作為很多子類的父類,它是一種模板式設計。而介面是一種行為規範,它是一種輻射式設計。什麼是模板式設計?最簡單例子,大家都用過ppt裡面的模板,如果用模板A設計了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它們的公共部分需要改動,則只需要改動模板A就可以了,不需要重新對ppt B和ppt C進行改動。而輻射式設計,比如某個電梯都裝了某種報警器,一旦要更新報警器,就必須全部更新。也就是說對於抽象類,如果需要添加新的方法,可以直接在抽象類中添加具體的實現,子類可以不進行變更;而對於介面則不行,如果介面進行了變更,則所有實現這個介面的類都必須進行相應的改動。

       下麵看一個網上流傳最廣泛的例子:門和警報的例子:門都有open( )和close( )兩個動作,此時我們可以定義通過抽象類和介面來定義這個抽象概念:

1 abstract class Door {
2     public abstract void open();
3     public abstract void close();
4 }

    或者:

1 interface Door {
2     public abstract void open();
3     public abstract void close();
4 }

  但是現在如果我們需要門具有報警alarm( )的功能,那麼該如何實現?下麵提供兩種思路:

  1)將這三個功能都放在抽象類裡面,但是這樣一來所有繼承於這個抽象類的子類都具備了報警功能,但是有的門並不一定具備報警功能;

  2)將這三個功能都放在介面裡面,需要用到報警功能的類就需要實現這個介面中的open( )和close( ),也許這個類根本就不具備open( )和close( )這兩個功能,比如火災報警器。

  從這裡可以看出, Door的open() 、close()和alarm()根本就屬於兩個不同範疇內的行為,open()和close()屬於門本身固有的行為特性,而alarm()屬於延伸的附加行為。因此最好的解決辦法是單獨將報警設計為一個介面,包含alarm()行為,Door設計為單獨的一個抽象類,包含open和close兩種行為。再設計一個報警門繼承Door類和實現Alarm介面。

 1 interface Alram {
 2     void alarm();
 3 }
 4  
 5 abstract class Door {
 6     void open();
 7     void close();
 8 }
 9  
10 class AlarmDoor extends Door implements Alarm {
11     void oepn() {
12       //....
13     }
14     void close() {
15       //....
16     }
17     void alarm() {
18       //....
19     }
20 }

  終於寫完了這篇博文,java的這三大特性是面向對象編程的核心和基礎,這裡的概念的理解對實際編程有非常大的幫助,可能內容過於繁冗了,如果對內容有疑問請在下麵留言或者私信我的郵箱,謝謝!!

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 大家都知道main方法的參數就是一個數組類型的,那麼它其實也是可以改成不定參數類型。我試了試,並調用了一些彈出來的方法。 嗯,我把Sting後面的“[ ]”換成了三個點(...),這三個點代表Java中的可變數組參數。可變的參數類型(variable argument type),也稱為不定參數類型 ...
  • 項目中需要對Excel進行操作,把數據中的數據寫入到Excel文件中。在數據量大的情況下,操作Excel是一件費時的操作。 但是執行到下列代碼時就會出現空指針的情況: 第四行返回的workbooks指針是一個空指針,無法進行向下的Excel操作。這是因為QAxObject對象是預設在單線程下使用, ...
  • 索引 簡述 準備 示例 效果圖 結語 簡述 我在使用opencv2或3的時候想要在圖片上添加中文文字,需要去下載Freetype庫,編譯好鏈接到opencv庫中才能中文的輸出。網上大部分在圖片中插入中文的教程還是win+vs的配置教程。像我這種win下有環境,linux下有環境的人來說,想要同步代碼 ...
  • 1.1 庫的概念 在我看來,庫是已經寫好的、成熟的、可復用的代碼。每個程式都需要依賴很多底層庫,不可能每個人的代碼從零開始編寫代碼,因此庫的存在具有非常重要的意義。 在我們的開發的應用中經常有一些公共代碼是需要反覆使用的,就把這些代碼編譯為庫文件。 庫可以簡單看成一組目標文件的集合,將這些目標文件經 ...
  • 在Java中,面向對象編程有三大特性:封裝、繼承、多態。 先來說說封裝。 封裝,顧名思義,就是通過抽象數據類型(即ADT,一種為了將數據類型和可能在該數據類型上進行操作而定義的)將數據以及基於數據的操作封裝在一起,使之成為獨立的“實體”。 首先先來看一個Person類: 對於封裝的思想,我們需要盡可 ...
  • wxPython是一套基於Python的GUI,可用Python製作圖形化界面程式。 本文內容為根據電子書“wxPython實戰(中文版)高清.pdf”整理,若有錯,歡迎指正。 註:雖然控制項可以使用pos參數指定位置,但推薦使用Sizer佈局控制項對應用程式整體進行佈局,佈局控制項的詳細方法可以參考電子 ...
  • 前 言 php easyui框架--本篇學習主要是 easyui中的datagrid(數據表格)框架。 本篇學習主要通過講解一段代碼加GIF圖片學習datagrid(數據表格)中的一些常用屬性,還有與之相關的dialog(對話窗)和texbobox(文本框)的一些常用屬性,希望對讀者有幫助。 本篇主 ...
  • 操作系統: CentOS 6.9_x64 python語言版本: 2.7.13 問題描述 現有一個tcp客戶端程式,需定期從伺服器取數據,但由於種種原因(網路不穩定等)需要自動重連。 測試伺服器示例代碼: https://github.com/mike-zhang/pyExamples/blob/m ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...