2010-02-17 11 views
9

tratando de sobrecargar el método estático java.lang.Math.sqrt para int Tipo:La sobrecarga de los Math.sqrt: la sobrecarga de métodos parece ocultar la original

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

surge un error extraño:

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

Pero cuando explícitamente haciendo referencia al método java.lang.Math.sqrt todo va bien:

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

El compilador utilizado es el estándar javac, versión 1.6.0_16.

Así que las preguntas son:

  1. ¿Por qué es el compilador no es capaz de resolver la sobrecarga en el primer caso?
  2. ¿Dónde se especifica este comportamiento en las especificaciones del lenguaje Java?

Gracias de antemano.

+0

¿Cuál es el error? – Pace

+1

Estrictamente hablando, no está sobrecargando ningún método aquí. –

Respuesta

13

sólo se puede sobrecargar los métodos de la misma clase. Es decir. si importa un método estático de otra clase y luego define su propio método con el mismo nombre, no habrá resolución de sobrecarga. La versión importada del método simplemente será ignorada.

cuanto a donde este comportamiento se especifica: la especificación del lenguaje define sobrecarga like this:

Si dos métodos de una clase (si ambos declarados en la misma clase, o ambos heredado por una clase, o uno declarado y uno heredado) tienen el mismo nombre, pero las firmas que no son anuladas equivalen, entonces se dice que el nombre del método está sobrecargado.

Tenga en cuenta que dice "dos métodos de una clase". Entonces los métodos importados de otra clase simplemente no son considerados.

Así que ya que su definición no es una sobrecarga de Math.sqrt, que sombras como por section 6.3.1 of the definition:

Una declaración d de un método denominado n sombras las declaraciones de otros métodos llamados n que se encuentran en un alcance adjunto en el punto donde d ocurre en todo el alcance de d.

+0

¡Esa es la respuesta! –

+0

Este comportamiento se describe en http://java.sun.com/docs/books/tutorial/java/IandI/override.html, en la sección sobre métodos de clase. – tonio

+1

@tonio: Su enlace es sobre anular versus esconderse, en lugar de sobrecargar versus sombreado, que es el problema aquí. – sepp2k

1

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

cambiar el nombre de función con un nombre diferente, si desea llamar Math.sqrt:

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

De simplemente omita la importación estática y use 'Math.sqrt()'. –

0

En la primera llamada, el método al que se hace referencia es el que ha devuelto, que espera que int sea su parámetro pero le está enviando el doble. por lo que da un error de compilación.

Pero con la segunda llamada se refiere a Math.sqrt() que funciona bien.

+0

¿por qué el down grade? Gramática? – redcayuga

2

No está sobrecargando. Las cosas están siendo colgadas por una ambigüedad; el compilador ve return sqrt(1.0 * n);, supone que está hablando de la función sqrt(int) en la clase Test, no la de lang.Math. Este es un comportamiento preferible; después de todo, probablemente no desee tener que especificar class.method cada vez que intente llamar a una función miembro. Y el compilador no lo resuelve porque en su situación particular, asume que ha cometido un error y no se da cuenta de que tenía la intención de llamar al sqrt en lang.Math.

3

Eso es bastante normal. Al escribir este código, no sobrecargó el método Math.sqrt de ninguna manera, simplemente definió un Test.sqrt(int) como argumento.

Luego está la cuestión de su mensaje de error.

Al definir el método Test.sqrt, sobrecarga (en esta clase) la importación estática que realizó.

Por lo tanto, cuando se llama a sqrt (1.0 * n), el compilador considera que intenta llamar a Test.sqrt (int) con un doble, lo que obviamente no es posible.

Cuestiones relacionadas