欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 重載、重寫、構(gòu)造函數(shù)的實例詳解

 更新時間:2017年09月19日 14:17:16   投稿:lqh  
這篇文章主要介紹了Java 重載、重寫、構(gòu)造函數(shù)的實例詳解的相關(guān)資料,希望通過本文大家能理解掌握java 面向?qū)ο蟮姆椒?,需要的朋友可以參考?/div>

Java 重載、重寫、構(gòu)造函數(shù)的實例詳解

方法重寫

1、重寫只能出現(xiàn)在繼承關(guān)系之中。當一個類繼承它的父類方法時,都有機會重寫該父類的方法。一個特例是父類的方法被標識為final。重寫的主要優(yōu)點是能夠定義某個子類型特有的行為。

class Animal {
    public void eat(){
      System.out.println ("Animal is eating.");
    }
  }

  class Horse extends Animal{
    public void eat(){
      System.out.println ("Horse is eating.");
    }
  }

2、對于從父類繼承來的抽象方法,要么在子類用重寫的方式設(shè)計該方法,要么把子類也標識為抽象的。所以抽象方法可以說是必須要被重寫的方法。

3、重寫的意義。

重寫方法可以實現(xiàn)多態(tài),用父類的引用來操縱子類對象,但是在實際運行中對象將運行其自己特有的方法。

public class Test {
    public static void main (String[] args) {
      Animal h = new Horse();
      h.eat(); 
    }
  }

  class Animal {
    public void eat(){
      System.out.println ("Animal is eating.");
    }
  }

  class Horse extends Animal{
    public void eat(){
      System.out.println ("Horse is eating.");
    }
    public void buck(){
    }
  }

  一個原則是:使用了什么引用,編譯器就會只調(diào)用引用類所擁有的方法。如果調(diào)用子類特有的方法,如上例的h.buck(); 編譯器會抱怨的(編譯錯誤)。也就是說,編譯器只看引用類型,而不是對象類型。

4、重寫方法的規(guī)則。

若想實現(xiàn)一個合格重寫方法,而不是重載,那么必須同時滿足下面的要求!

A、重寫規(guī)則之一:重寫方法不能比被重寫方法限制有更嚴格的訪問級別。
(但是可以更廣泛,比如父類方法是包訪問權(quán)限,子類的重寫方法是public訪問權(quán)限。)
比如:Object類有個toString()方法,開始重寫這個方法的時候我們總?cè)菀淄沺ublic修飾符,編譯器當然不會放過任何教訓(xùn)我們的機會。出錯的原因就是:沒有加任何訪問修飾符的方法具有包訪問權(quán)限,包訪問權(quán)限比public當然要嚴格了,所以編譯器會報錯的。

B、重寫規(guī)則之二:參數(shù)列表必須與被重寫方法的相同。

重寫有個孿生的弟弟叫重載,也就是后面要出場的。如果子類方法的參數(shù)與父類對應(yīng)的方法不同,那么就是你認錯人了,那是重載,不是重寫。

C、重寫規(guī)則之三:**返回類型必須與被重寫方法的返回類型相同。

父類方法A:void eat(){} 子類方法B:int eat(){} 兩者雖然參數(shù)相同,可是返回類型不同,所以不是重寫。**

父類方法A:int eat(){} 子類方法B:long eat(){} 返回類型雖然兼容父類,但是不同就是不同,所以不是重寫。

D、重寫規(guī)則之四:重寫方法不能拋出新的異?;蛘弑缺恢貙懛椒暶鞯臋z查異常更廣的檢查異常。但是可以拋出更少,更有限或者不拋出異常。

import java.io.*;
  /**
  * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java!
  */
  public class Test {
    public static void main (String[] args) {
      Animal h = new Horse();
      try {
        h.eat(); 
      }
      catch (Exception e) {
      }
    }
  }

  class Animal {
    public void eat() throws Exception{
      System.out.println ("Animal is eating.");
      throw new Exception();
    }
  }

  class Horse extends Animal{
    public void eat() throws IOException{
      System.out.println ("Horse is eating.");
      throw new IOException();
    }
  }

  這個例子中,父類拋出了檢查異常Exception,子類拋出的IOException是Exception的子類,也即是比被重寫的方法拋出了更有限的異常,這是可以的。如果反過來,父類拋出IOException,子類拋出更為寬泛的Exception,那么不會通過編譯的。
注意:這種限制只是針對檢查異常,至于運行時異常RuntimeException及其子類不再這個限制之中。

E、重寫規(guī)則之五:不能重寫被標識為final的方法。

F、重寫規(guī)則之六:如果一個方法不能被繼承,則不能重寫它。

比較典型的就是父類的private方法。下例會產(chǎn)生一個有趣的現(xiàn)象。

public class Test {
    public static void main (String[] args) {
      //Animal h = new Horse();
      Horse h = new Horse();
      h.eat();
    }
  }

  class Animal {
    private void eat(){
      System.out.println ("Animal is eating.");
    }
  }

  class Horse extends Animal{
    public void eat(){
      System.out.println ("Horse is eating.");
    }
  }

  這段代碼是能通過編譯的。表面上看來違反了第六條規(guī)則,但實際上那是一點巧合。Animal類的eat()方法不能被繼承,因此Horse類中的 eat()方法是一個全新的方法,不是重寫也不是重載,只是一個只屬于Horse類的全新的方法!這點讓很多人迷惑了,但是也不是那么難以理解。

main()方法如果是這樣:

  Animal h = new Horse();
  //Horse h = new Horse();
  h.eat();

編譯器會報錯,為什么呢?Horse類的eat()方法是public的?。?yīng)該可以調(diào)用??!請牢記,多態(tài)只看父類引用的方法,而不看子類對象的方法!

方法的重載

重載是友好的,它不要求你在調(diào)用一個方法之前轉(zhuǎn)換數(shù)據(jù)類型,它會自動地尋找匹配的方法。方法的重載是在編譯時刻就決定調(diào)用哪個方法了,和重寫不同。最最常用的地方就是構(gòu)造器的重載。

1、基本數(shù)據(jù)類型參數(shù)的重載。

/**
 * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java!
 */
public class Test {
    static void method(byte b){
      System.out.println ("method:byte");
    }
    static void method(short s){
      System.out.println ("method:short");
    }
    static void method(int i){
      System.out.println ("method:int");
    }
    static void method(float f){
      System.out.println ("method:float");
    }
    static void method(double d){
      System.out.println ("method:double");
    }
    public static void main (String[] args) {
      method((byte)1);
      method('c');
      method(1);
      method(1L);
      method(1.1);
      method(1.1f);
    }
  }

輸出結(jié)果:

method:byte
method:int
method:int
method:float
method:double
method:float

  可以看出:首先要尋找的是數(shù)據(jù)類型正好匹配方法。如果找不到,那么就提升為表達能力更強的數(shù)據(jù)類型,如上例沒有正好容納long的整數(shù)類型,那么就轉(zhuǎn)換為 float類型的。如果通過提升也不能找到合適的兼容類型,那么編譯器就會報錯。反正是不會自動轉(zhuǎn)換為較小的數(shù)據(jù)類型的,必須自己強制轉(zhuǎn)換,自己來承擔轉(zhuǎn)變后果。

  char類型比較特殊,如果找不到正好匹配的類型,它會轉(zhuǎn)化為int而不是short,雖然char是16位的。

2、重載方法的規(guī)則。

A、被重載的方法必須改變參數(shù)列表。

參數(shù)必須不同,這是最重要的!不同有兩個方面,參數(shù)的個數(shù),參數(shù)的類型,參數(shù)的順序。

B、被重載的方法與返回類型無關(guān)。

也就是說,不能通過返回類型來區(qū)分重載方法。

C、被重載的方法可以改變訪問修飾符。

沒有重寫方法那樣嚴格的限制。

D、被重載的方法可以聲明新的或者更廣的檢查異常。

沒有重寫方法那樣嚴格的限制。

E、方法能夠在一個類中或者在一個子類中被重載。

3、帶對象引用參數(shù)的方法重載。

class Animal {}
  class Horse extends Animal{}

  public class Test {
    static void method(Animal a){
      System.out.println ("Animal is called.");
    }
    static void method(Horse h){
      System.out.println ("Horse is called.");
    }
    public static void main (String[] args) {
      Animal a = new Animal();
      Horse h = new Horse();
      Animal ah = new Horse();

      method(a);
      method(h);
      method(ah);
    }
  }

輸出結(jié)果是:

Animal is called.
Horse is called.
Animal is called.

前兩個輸出沒有任何問題。第三個方法為什么不是輸出“Horse is called.”呢?還是那句老話,要看引用類型而不是對象類型,方法重載是在編譯時刻就決定的了,引用類型決定了調(diào)用哪個版本的重載方法。

4、重載和重寫方法區(qū)別的小結(jié)。

如果能徹底弄明白下面的例子,說明你對重載和重寫非常了解了,可以結(jié)束這節(jié)的復(fù)習(xí)了。

class Animal {
    public void eat(){
      System.out.println ("Animal is eating."); 
    }
  }
  class Horse extends Animal{
    public void eat(){
      System.out.println ("Horse is eating."); 
    }
    public void eat(String food){
      System.out.println ("Horse is eating " + food);
    }
  }

  public class Test {
    public static void main (String[] args) {
      Animal a = new Animal();
      Horse h = new Horse();
      Animal ah = new Horse();

      a.eat();
      h.eat();
      h.eat("apple");
      ah.eat();
      //a.eat("apple");
      //ah.eat("apple");
    }
  }

四個輸出分別是什么?被注釋的兩條語句為什么不能通過編譯?

第一條:a.eat(); 普通的方法調(diào)用,沒有多態(tài),沒什么技術(shù)含量。調(diào)用了Animal類的eat()方法,輸出:Animal is eating.
第二條:h.eat(); 普通的方法調(diào)用,也沒什么技術(shù)含量。調(diào)用了Horse類的eat()方法,輸出:Horse is eating.
第三條:h.eat(“apple”); 重載。Horse類的兩個eat()方法重載。調(diào)用了Horse類的eat(String food)方法,輸出:Horse is eating apple
第四條:ah.eat(); 多態(tài)。前面有例子了,不難理解。輸出:Horse is eating.
第五條:a.eat(“apple”); 低級的錯誤,Animal類中沒有eat(String food)方法。因此不能通過編譯。
第六條:ah.eat(“apple”); 關(guān)鍵點就在這里。解決的方法還是那句老話,不能看對象類型,要看引用類型。Animal類中沒有eat(String food)方法。因此不能通過編譯。

小結(jié)一下:多態(tài)不決定調(diào)用哪個重載版本;多態(tài)只有在決定哪個重寫版本時才起作用。

重載對應(yīng)編譯時,重寫對應(yīng)運行時。夠簡潔的了吧!

構(gòu)造方法

構(gòu)造方法是一種特殊的方法,沒有構(gòu)造方法就不能創(chuàng)建一個新對象。實際上,不僅要調(diào)用對象實際類型的構(gòu)造方法,還要調(diào)用其父類的構(gòu)造方法,向上追溯,直到 Object類。構(gòu)造方法不必顯式地調(diào)用,當使用new關(guān)鍵字時,相應(yīng)的構(gòu)造方法會自動被調(diào)用。

1、構(gòu)造方法的規(guī)則。

A、構(gòu)造方法能使用任何訪問修飾符。包括private,事實上java類庫有很多都是這樣的,設(shè)計者不希望使用者創(chuàng)建該類的對象。

B、構(gòu)造方法的名稱必須與類名相同。這樣使得構(gòu)造方法與眾不同,如果我們遵守sun的編碼規(guī)范,似乎只有構(gòu)造方法的首字母是大寫的。

C、構(gòu)造方法不能有返回類型。

反過來說,有返回類型的不是構(gòu)造方法

  public class Test {
    int Test(){
      return 1;
    }
  }

這個方法是什么東西?一個冒充李逵的李鬼而已,int Test()和其他任何普通方法沒什么兩樣,就是普通的方法!只不過看起來很惡心,類似惡心的東西在考試卷子里比較多。

D、如果不在類中創(chuàng)建自己的構(gòu)造方法,編譯器會自動生成默認的不帶參數(shù)的構(gòu)造函數(shù)。

這點很容易驗證!寫一個這樣簡單的類,編譯。

class Test {
}

對生成的Test.class文件反編譯:javap Test,可以看到:

D:"JavaCode"bin>javap Test
Compiled from "Test.java"
class Test extends java.lang.Object{
  Test();
}

看到編譯器自動添加的默認構(gòu)造函數(shù)了吧!

E、如果只創(chuàng)建了帶參數(shù)的構(gòu)造方法,那么編譯器不會自動添加無參的構(gòu)造方法的!

F、在每個構(gòu)造方法中,如果使用了重載構(gòu)造函數(shù)this()方法,或者父類的構(gòu)造方法super()方法,那么this()方法或者super()方法必須放在第一行。而且這兩個方法只能選擇一個,因此它們之間沒有順序問題。

G、除了編譯器生成的構(gòu)造方法,而且沒有顯式地調(diào)用super()方法,那么編譯器會插入一個super()無參調(diào)用。

H、抽象類有構(gòu)造方法。

靜態(tài)方法的重載與重寫(覆蓋)

1、靜態(tài)方法是不能被覆蓋的??梢苑謨煞N情況討論:

A、子類的非靜態(tài)方法“覆蓋”父類的靜態(tài)方法。

這種情況下,是不能通過編譯的。

class Father{
   static void print(){
     System.out.println ( " in father  method " );
   }
}
class Child extends Father{
   void print(){
     System.out.println ( " in child method " );
   }
}

static方法表示該方法不關(guān)聯(lián)具體的類的對象,可以通過類名直接調(diào)用,也就是編譯的前期就綁定了,不存在后期動態(tài)綁定,也就是不能實現(xiàn)多態(tài)。子類的非靜態(tài)方法是與具體的對象綁定的,兩者有著不同的含義。

B、子類的靜態(tài)方法“覆蓋”父類靜態(tài)方法。

這個覆蓋依然是帶引號的。事實上把上面那個例子Child類的print方法前面加上static修飾符,確實能通過編譯!但是不要以為這就是多態(tài)!多態(tài)的特點是動態(tài)綁定,看下面的例子:

class Father{
   static void print(){
     System.out.println ( " in father  method " );
   }
}
class Child extends Father{
   static void print(){
     System.out.println ( " in child method " );
   }
}

class Test{
   public static void main (String[] args) {
     Father f = new Child();
     f.print();
   }
}

輸出結(jié)果是:in father method

從這個結(jié)果可以看出,并沒有實現(xiàn)多態(tài)。

但是這種形式很迷惑人,貌似多態(tài),實際編程中千萬不要這樣搞,會把大家搞懵的!

它不符合覆蓋表現(xiàn)出來的特性,不應(yīng)該算是覆蓋!

總而言之,靜態(tài)方法不能被覆蓋。

2、靜態(tài)方法可以和非靜態(tài)方法一樣被重載。

這樣的例子太多了,我不想寫例程了??纯磈ava類庫中很多這樣的例子。

如java.util.Arrays類的一堆重載的binarySearch方法。

在這里提一下是因為查資料時看到這樣的話“sun的SL275課程說,靜態(tài)方法只能控制靜態(tài)變量(他們本身沒有),靜態(tài)方法不能被重載和覆蓋……”

大家不要相信??!可以重載的。而且靜態(tài)與非靜態(tài)方法可以重載。

從重載的機制很容易就理解了,重載是在編譯時刻就決定的了,非靜態(tài)方法都可以,靜態(tài)方法怎么可能不會呢?

如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

  • java中的方法重載知識點總結(jié)

    java中的方法重載知識點總結(jié)

    在本篇文章里小編給大家整理了關(guān)于java中的方法重載知識點總結(jié),有興趣的朋友們可以跟著學(xué)習(xí)參考下。
    2020-02-02
  • Java多線程——基礎(chǔ)概念

    Java多線程——基礎(chǔ)概念

    這篇文章主要介紹了java多線程編程實例,分享了幾則多線程的實例代碼,具有一定參考價值,加深多線程編程的理解還是很有幫助的,需要的朋友可以參考下,希望可以幫到你
    2021-07-07
  • SpringCloud使用logback日志框架教程詳解

    SpringCloud使用logback日志框架教程詳解

    Logback是一個功能強大的日志框架,它是一個基于slf4j的日志系統(tǒng),提供了可靠的日志服務(wù),比log4j更快,更靈活,更容易使用。本文將教會你快速讓你的項目集成logback日志框架,需要的朋友可以參考下
    2023-05-05
  • Java結(jié)構(gòu)型設(shè)計模式之橋接模式詳細講解

    Java結(jié)構(gòu)型設(shè)計模式之橋接模式詳細講解

    橋接,顧名思義,就是用來連接兩個部分,使得兩個部分可以互相通訊。橋接模式將系統(tǒng)的抽象部分與實現(xiàn)部分分離解耦,使他們可以獨立的變化。本文通過示例詳細介紹了橋接模式的原理與使用,需要的可以參考一下
    2022-09-09
  • springcloud-gateway整合jwt+jcasbin實現(xiàn)權(quán)限控制的詳細過程

    springcloud-gateway整合jwt+jcasbin實現(xiàn)權(quán)限控制的詳細過程

    這篇文章主要介紹了springcloud-gateway整合jwt+jcasbin實現(xiàn)權(quán)限控制,基于springboot+springcloud+nacos的簡單分布式項目,項目交互采用openFeign框架,單獨提取出來成為一個獨立的model,需要的朋友可以參考下
    2023-02-02
  • dm.jdbc.driver.DMException網(wǎng)絡(luò)通信異常的解決過程

    dm.jdbc.driver.DMException網(wǎng)絡(luò)通信異常的解決過程

    最近一個項目里面出現(xiàn)了一個比較詭異的問題,給大家分享下,這篇文章主要給大家介紹了關(guān)于dm.jdbc.driver.DMException網(wǎng)絡(luò)通信異常的解決過程,需要的朋友可以參考下
    2023-02-02
  • 在Spring Boot中如何使用Cookies詳析

    在Spring Boot中如何使用Cookies詳析

    這篇文章主要給大家介紹了關(guān)于在Spring Boot中如何使用Cookies的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • java模式匹配之蠻力匹配

    java模式匹配之蠻力匹配

    這篇文章主要介紹了java模式匹配之蠻力匹配的相關(guān)資料和代碼,需要的朋友可以參考下
    2015-05-05
  • Java8并行流中自定義線程池操作示例

    Java8并行流中自定義線程池操作示例

    這篇文章主要介紹了Java8并行流中自定義線程池操作,結(jié)合實例形式分析了并行流的相關(guān)概念、定義及自定義線程池的相關(guān)操作技巧,需要的朋友可以參考下
    2019-05-05
  • WebsocketClient斷線的一些常見原因及解決辦法

    WebsocketClient斷線的一些常見原因及解決辦法

    這篇文章主要給大家介紹了關(guān)于WebsocketClient斷線的一些常見原因及解決辦法,文中通過代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用WebsocketClient斷線具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-12-12

最新評論