java中重載overloading與重寫overriding

常見面試題是關于重載(overloading)方法和重寫(overriding)方法的。

代碼如下

public class MethodOverrideVsOverload {

public boolean equals( MethodOverrideVsOverload other ) {
System.out.println("MethodOverrideVsOverload equals method reached" );
return true;
}

public static void main(String[] args) {
Object o1 = new MethodOverrideVsOverload();
Object o2 = new MethodOverrideVsOverload();

MethodOverrideVsOverload o3 = new MethodOverrideVsOverload();
MethodOverrideVsOverload o4 = new MethodOverrideVsOverload();

if(o1.equals(o2)){
System.out.println("objects o1 and o2 are equal");
}

if(o3.equals(o4)){
System.out.println("objects o3 and o4 are equal");
}
}
}


A.輸出結果是:

MethodOverrideVsOverload equals method reached

objects o3 and o4 are equal

這個問題考察了哪些概念呢?

•Java語言中,一個類只能從一個類中繼承出來(也就是,單繼承結構),如果沒有顯式的標明所繼承自的類,那麽自動繼承自Object對象。
•大多數的非final對象類方法都會被子類重寫(overridden):
public boolean equals(Object obj); // make note of this method

public int hashCode();

public String toString();

•重載方法在編譯時起作用(例如,靜態綁定),重寫方法在運行時起作用(例如,動態綁定)。靜態綁定意味著JVM在編譯時決定調用的類或方法。而動態綁定時,JVM是在運行時決定調用的類或方法。動態綁定設計是多態的基礎。更多了解編譯時和運行時.
•子類中重寫父類的對應方法必須遵循下面的規則:
參數 不可變(譯者注:包括參數類型和個數)。
返回類型 不可變,除了協變返回類型或其子類型(covariant (subtype) returns)。
異常 子類中可以抛出更少的異常,但絕對不能抛出父類中沒有定義的已檢查異常。
訪問權限 比父類中對應方法更寬松。
調用 運行時(也就是動態綁定),根據對象類型來決定調用的具體方法。

現在,再回頭看上面的代碼,MethodOverrideVsOverload 類中的”equals(MethodOverrideVsOverload other)” 方法並沒有重寫Object類中的”public boolean equals(Object obj)” 方法。這是因爲其違背了參數規則,其中一個是MethodOverrideVsOverload 類型,而另一個是Object類型。因此,這兩個方法是重載關系(發生在編譯時),而不是重寫關系。

因此,當調用o1.equals(o2)時,實際上調用了object類中的public boolean equals(Object obj)方法。這是因爲在編譯時,o1和o2都是Object類型,而Object類的equals( … )方法是比較記憶體地址(例如,Object@235f56和Object@653af32)的,因此會返回false。

當調用o3.equals(o4)時,實際上調用了MethodOverrideVsOverload 類中的equals( MethodOverrideVsOverload other )方法。這是因爲在編譯時,o3和o4都是MethodOverrideVsOverload類型的,因此得到上述結果。

接下來還可以怎麽提問呢?

Q.那怎麽解決上面的那個問題呢?

A.在Java5中,新增了注解,其中包括很好用的編譯時注解(compile time annotations)@override,來保證方法正確的重寫了父類方法。如果在上面的代碼中添加了注解,那麽JVM會抛出一個編譯錯誤。

因此,解決的方法就是給MethodOverrideVsOverload 類的boolean equals( MethodOverrideVsOverload other )方法添加@override注解。這樣的話編譯時就會有錯誤抛出來提示開發者某個方法沒有正確的重寫父類方法。之後,還需要修改方法的參數,將其從 Object變成MethodOverrideVsOverload,具體如下:

代碼如下

View Code
public class MethodOverrideVsOverload {

@Override
public boolean equals( Object other ) {
System.out.println("MethodOverrideVsOverload equals method reached" );
return true;
}

public static void main(String[] args) {
Object o1 = new MethodOverrideVsOverload(); //during compile time o1 is of type Object
//during runtime o1 is of type MethodOverrideVsOverload
Object o2 = new MethodOverrideVsOverload(); //during compile time o2 is of type Object
//during runtime o2 is of type MethodOverrideVsOverload

MethodOverrideVsOverload o3 = new MethodOverrideVsOverload(); //o3 is of type MethodOverrideVsOverload
// during both compile time and runtime
MethodOverrideVsOverload o4 = new MethodOverrideVsOverload(); //o4 is of type MethodOverrideVsOverload
// during both compile time and runtime

if(o1.equals(o2)){
System.out.println("objects o1 and o2 are equal");
}

if(o3.equals(o4)){
System.out.println("objects o3 and o4 are equal");
}

}

}

輸出爲:

代碼如下

MethodOverrideVsOverload equals method reached

objects o1 and o2 are equal

MethodOverrideVsOverload equals method reached

objects o3 and o4 are equal

更多相關文章
  • 本文章介紹一篇關于重載(overload).覆蓋(override).隱藏(hide)介紹與區別,有需要的同學可以參考一下. 這三個概念都是與OO中的多態有關系的.如果單是區別重載與覆蓋這兩個概念是比較容易的,但是隱
  • 我們知道在PHP中沒有函數重載這個概念,讓很多時候我們無法進行一些處理,甚至有時候不得不在函數後面定義好N個參數只有使用func_get_arg,func_get_args,func_num_args實現僞重載了,下
  • 在linux中關機與重啓伺服器都是使用了shutdown命令,只是後面的參考不同罷了,下面大家可參考參考.重啓命令:1.reboot2.shutdown -r now 立刻重啓(root用戶使用)3.shutdown -r 10 過10分鍾自動重啓(root用戶使用)4.shutdown -r 20 ...
  • WebService中方法的重載問題分析
    文章介紹一下關于WebService中方法的重載問題分析,有需要了解的朋友可以參考一下.一
  • 下面我們一起來看看在Java中List與Map初始化的一些寫法,希望文章對各位同學會帶來幫助哦.Java的在還沒有發現新寫法之前時,我一直是這麽初始化List跟Map: 代碼如下 //初始化List List<str
  • 本人對于struts2是不懂的但是看到一個站長分享了這個文件上傳下載功能感覺非常的好用並且覺得比php還簡單,所以轉過來給大家分享一下,希望學習這個的少走彎路了.1.文件上傳首先是jsp頁面的代碼在jsp頁面中定義一個上傳標簽 代碼如下 <tr> <td align="r ...
  • 在于java中Statement和PreparedStatement了,在java升級過程中PreparedStatement是在安全與效能及用法上都非常的成熟了,下面我們一起來看看這兩者的區別吧.1.PreparedStatement是預編譯的,對于批量處理可以大大提高效率. 也叫JDBC存儲過程 ...
  • 學習php的朋友都知道php本身是沒有函數重載這一說的更沒說像java,c那樣使用方法,但如果我們深入了解一下會發現要吧在php中使用func_get_args()和func_num_args()函數實現函數重載哦,
一周排行