首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 每日一題:方法重寫與可變參數簽名不匹配導致編譯錯誤

     編輯:Java 相關知識

每日一題:考察子類重寫父類方法時,可變參數 int... nums 與陣列參數 int[] nums 在簽名層面的差異,導致編譯失敗。

題目代碼

class Parent {
    public void sum(int num1, int... nums) {
        System.out.println("Parent... sum");
    }
}

class Sub extends Parent {
    @Override
    public void sum(int num1, int[] nums) {
        System.out.println("Sub... sum");
    }
}

public class Test {
    public static void main(String[] args) {
        Parent p = new Sub();
        p.sum(1, 2);
        Sub s = new Sub();
        s.sum(1, 2);
    }
}

問題:主程序是否有編譯錯誤?

答案:有編譯錯誤,錯誤發生在 Sub 類的 @Override 方法聲明處。

錯誤原因深度解析

可變參數本質是陣列,但簽名不同

  • 父類:void sum(int num1, int... nums) → 編譯後簽名 (I[I)V (參數類型:int, int[])
  • 子類:void sum(int num1, int[] nums) → 編譯後簽名 (I[I)V (參數類型:int, int[])
  • JVM 層面擦除後簽名相同,但 Java 語言層面方法簽名包含「是否可變參數」標記 (ACC_VARARGS 訪問標志)。

JLS §8.4.2 規定

兩個方法若擁有相同的方法名、類型參數、參數類型列表,但其中一個是可變參數方法而另一個不是,則它們不是重寫關係,而是重載關係。

因此 Sub.sum(int, int[]) 無法重寫Parent.sum(int, int...),編譯器報錯:

error: method does not override or implement a method from a supertype
    @Override
    public void sum(int num1, int[] nums) {
    ^

驗證:去掉 @Override 會怎樣?

class Sub extends Parent {
    // 無 @Override,視為重載
    public void sum(int num1, int[] nums) { ... }
}
  • 編譯通過,但 破壞多態:
  • Parent p = new Sub(); p.sum(1,2); 調用父類可變參數版(輸出 Parent... sum)。
  • Sub s = new Sub(); s.sum(1,2); 調用子類陣列版(輸出 Sub... sum)。
  • 同一引用類型不同調用行為不一致,極易產生 Bug。

正確重寫姿勢

  1. 保持簽名完全一致:子類也用 int... nums。
  2. 或統一用陣列:父類改為 int[] nums,調用處顯式傳陣列 sum(1, new int[]{2})。
// 正確重寫
class Sub extends Parent {
    @Override
    public void sum(int num1, int... nums) {
        System.out.println("Sub... sum");
    }
}

面試延伸:可變參數與重載/重寫的其他坑

場景結果說明
父類 void m(int...),子類 void m(int[])編譯錯誤 (加 @Override)簽名不匹配
父類 void m(int[]),子類 void m(int...)編譯錯誤同上
同類內 void m(int...) + void m(int[])編譯錯誤重載簽名衝突 (擦除後相同)
調用 m(1,2,3) 匹配哪個?優先匹配固定參數若只有可變參數版則匹配它

總結

可變參數不是陣列的語法糖,它在方法簽名中帶有 ACC_VARARGS 標記。重寫要求簽名完全一致(含可變參數標記),重載不允許擦除後簽名相同。記住鐵律:父類用可變參數,子類重寫必須也用可變參數;父類用陣列,子類重寫必須也用陣列。這道題精準考察對 Java 方法解析機制的深度理解。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved