2010-02-17 32 views
9

試圖重載java.lang.Math.sqrt靜態方法int類型:超載Math.sqrt的:重載方法似乎隱藏原來的

import static java.lang.Math.sqrt; 

class Test 
{ 
    private static double sqrt(int n) 
    { 
     return sqrt(1.0 * n); 
    } 

    public static void main(String[] args) 
    { 
     System.out.println(sqrt(1)); 
    } 
} 

一個奇怪的錯誤出現了:

Test.java:7: sqrt(int) in Test cannot be applied to (double) 
       return sqrt(1.0 * n); 
        ^
1 error 

但是,當明確參考java.lang.Math.sqrt方法一切都很好:

class Test 
{ 
    private static double sqrt(int n) 
    { 
     return Math.sqrt(1.0 * n); 
    } 

    public static void main(String[] args) 
    { 
     System.out.println(sqrt(1)); 
    } 
} 

使用的編譯器是標準的javac,版本1.6.0_16

所以問題是:

  1. 爲什麼編譯器不能夠解決在第一種情況下超載?
  2. 此行爲在java語言規範中指定的位置?

在此先感謝。

+0

什麼是錯誤? – Pace 2010-02-17 13:21:09

+1

嚴格地說,你不會在這裏重載任何方法。 – 2010-02-17 13:21:57

回答

13

只能超載在同一個類中的方法。即如果您導入另一個類的靜態方法,然後使用相同名稱定義自己的方法,則不會有重載解決方案。該方法的導入版本將被簡單地忽略。

關於指定了此行爲,其中:語言規範定義重載like this

如果一個類的兩個方法(在相同的類是否都聲明,或由類都繼承,或一個所聲明的和一個是繼承的)具有相同的名稱,但簽名不是覆蓋等效的,那麼方法名稱被稱爲重載。

請注意,它說「一類的兩種方法」。所以從另一個類導入的方法根本不被考慮。

那麼既然你的定義是不Math.sqrt的過載,它陰影它作爲每section 6.3.1 of the definition

一個名爲N的方法的聲明d陰影名爲N的任何其他方法,這些方法在聲明d在整個d範圍內出現的一個封閉範圍。

+0

這就是答案! – 2010-02-17 13:27:19

+0

此行爲在http://java.sun.com/docs/books/tutorial/java/IandI/override.html中有關類方法的部分中進行了描述。 – tonio 2010-02-17 13:28:30

+1

@tonio:你的鏈接是關於重寫與隱藏,而不是重載與陰影,這是問題在這裏。 – sepp2k 2010-02-17 13:39:55

1

是,sqrt(int) in Test cannot be applied to (double)

重命名功能與不同的名稱,如果你想調用Math.sqrt:

private static double mysqrt(int n) 
{ 
    return sqrt(1.0 * n); 
} 
+0

簡單地跳過靜態導入並使用'Math.sqrt()'。 – 2010-02-17 13:34:10

0

在第一個調用中,引用的方法是您返回的方法,它將int作爲其參數,但是您將向其發送雙精度值。所以它給出了一個編譯器錯誤。

但第二次調用你指Math.sqrt(),它工作正常。

+0

爲什麼降檔?語法? – redcayuga 2010-02-17 15:02:00

2

你實際上並沒有超載。事情被籠罩在模棱兩可之上;編譯器看到return sqrt(1.0 * n);,它假定您正在談論類Test中的sqrt(int)函數,而不是lang.Math中的函數。這是更好的行爲;畢竟,您可能不希望在每次嘗試調用成員函數時都指定class.method。編譯器沒有解決它是因爲在你的特定情況下,它假定你犯了一個錯誤,並沒有意識到你打算調用lang.Math中的sqrt

3

這很正常。 通過編寫此代碼,您沒有以任何方式重載Math.sqrt方法,只需將Test.sqrt(int)定義爲參數即可。

然後是你的錯誤信息的問題。

定義Test.sqrt方法時,您重載(在此類中)您所做的靜態導入。

所以,當調用sqrt(1.0 * n)時,編譯器會考慮用雙精度調用Test.sqrt(int),這顯然是不可能的。