2010-02-17 5 views
9

cercando di sovraccaricare il metodo statico java.lang.Math.sqrt per int Tipo:Sovraccarico di Math.sqrt: metodo di sovraccarico sembra nascondere l'originale

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)); 
    } 
} 

nasce un errore strano:

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

Ma quando esplicitamente riferimento il metodo java.lang.Math.sqrt tutto sta andando bene:

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)); 
    } 
} 

Il compilatore utilizzato è lo standard javac, versione 1.6.0_16.

Quindi le domande sono:

  1. Perché il compilatore non è in grado di risolvere il sovraccarico nel primo caso?
  2. Dove viene specificato questo comportamento nelle specifiche del linguaggio Java?

Grazie in anticipo.

+0

Qual è l'errore? – Pace

+1

Strettamente parlando non stai sovraccaricando alcun metodo qui. –

risposta

13

È possibile sovraccaricare solo metodi nella stessa classe. Cioè se si importa un metodo statico di un'altra classe e quindi si definisce il proprio metodo con lo stesso nome, non vi sarà alcuna risoluzione di sovraccarico. La versione importata del metodo sarà semplicemente ignorata.

Per quanto riguarda in cui viene specificato questo comportamento: La specifica del linguaggio definisce sovraccarico like this:

Se due metodi di una classe (se sia dichiarato nella stessa classe, o entrambi ereditato da una classe, o di una dichiarata e uno ereditato) hanno lo stesso nome ma le firme che non sono override-equivalenti, quindi si dice che il nome del metodo sia sovraccarico.

Si noti che si dice "due metodi di una classe". Quindi i metodi importati da un'altra classe non sono semplicemente considerati.

Quindi, dato la sua definizione non è un sovraccarico di Math.sqrt, esso ombre come per section 6.3.1 of the definition:

Una dichiarazione d di un metodo denominato n ombre le dichiarazioni di tutti gli altri metodi chiamati n che sono un ambito che racchiude nel punto in cui d si verifica in tutto lo scopo di d.

+0

Questa è la risposta! –

+0

Questo comportamento è descritto in http://java.sun.com/docs/books/tutorial/java/IandI/override.html, nella sezione sui metodi di classe. – tonio

+1

@tonio: il tuo link parla di ignorare rispetto a nascondere, invece di sovraccaricare rispetto a shadowing, che è il problema qui. – sepp2k

1

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

rinominare la funzione con nome diverso, se si desidera chiamare Math.sqrt:

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

Basta saltare l'importazione statica e usare 'Math.sqrt()'. –

0

Nella prima chiamata il metodo indicato è quello che si è restituito che prevede che int sia il suo parametro ma che si sta inviando il doppio. quindi dà un errore del compilatore.

Ma con la seconda chiamata ci si riferisce a Math.sqrt() che funziona correttamente.

+0

perché il down grade? grammatica? – redcayuga

2

In realtà non si sta sovraccaricando. Le cose vengono sospese su un'ambiguità; il compilatore vede return sqrt(1.0 * n);, si presuppone che si stia parlando della funzione sqrt(int) nella classe Test, non quella in lang.Math. Questo è un comportamento preferibile; dopo tutto, probabilmente non si desidera specificare class.method ogni volta che si sta tentando di chiamare una funzione membro. E il compilatore non lo risolve perché nella tua situazione specifica, si presuppone che tu abbia commesso un errore e non ti accorgerai di voler chiamare lo sqrt in lang.Math.

3

Questo è abbastanza normale. Scrivendo questo codice, non hai sovraccaricato il metodo Math.sqrt in alcun modo, hai semplicemente definito un argomento come Test.sqrt(int).

Poi c'è la domanda del tuo messaggio di errore.

Quando si definisce il metodo Test.sqrt, si sovraccarica (in questa classe) l'importazione statica apportata.

Quindi, quando si chiama sqrt (1.0 * n), il compilatore considera di provare a chiamare Test.sqrt (int) con un doppio, che ovviamente non è possibile.