views:

238

answers:

5

Hello,

trying to overload the java.lang.Math.sqrt static method for int type :

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

an odd error arises :

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

But when explicitly referencing the java.lang.Math.sqrt method all is going fine :

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

The compiler used is the standard javac, version 1.6.0_16.

So the questions are :

  1. Why is the compiler not able to resolve the overloading in the first case ?
  2. Where does this behavior is specified in the java language specifications ?

Thanks in advance.

A: 

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

Rename your fucntion with different name, if you wish to call Math.sqrt:

private static double mysqrt(int n)
{
    return sqrt(1.0 * n);
}
splix
Of simply skip the static import and use `Math.sqrt()`.
Joachim Sauer
+10  A: 

You can only overload methods in the same class. I.e. if you import a static method of another class and then define your own method with the same name, there will be no overload resolution. The imported version of the method will simply be ignored.

Regarding where this behavior is specified: The language specification defines overloading like this:

If two methods of a class (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the same name but signatures that are not override-equivalent, then the method name is said to be overloaded.

Note that it says "two methods of a class". So methods imported from another class are simply not considered.

So since your definition is not an overload of Math.sqrt, it shadows it as per section 6.3.1 of the definition:

A declaration d of a method named n shadows the declarations of any other methods named n that are in an enclosing scope at the point where d occurs throughout the scope of d.

sepp2k
That's the answer!
DR
This behavior is described in http://java.sun.com/docs/books/tutorial/java/IandI/override.html, in the section about class methods.
tonio
@tonio: Your link is about overriding versus hiding, as opposed to overloading versus shadowing, which is the issue here.
sepp2k
@sepp2k: thanks for your clarification and the correct link to the java spec !
tonio
@sepp2K : thanks a lot for your complete and accurate answer.
Serious
A: 

In the first call the method referred is the one which you have return which expect int to be its parameter but you are sending double to it. so it gives a compiler error.

But with the second call you are referring to Math.sqrt() which works fine.

GK
why the down grade? grammer?
+1  A: 

You're not actually overloading. Things are being hung up over an ambiguity; the compiler sees return sqrt(1.0 * n);, it assumes you're talking about the sqrt(int) function in class Test, not the one in lang.Math. This is preferable behavior; after all, you probably don't want to have to specify class.method every time you're trying to call a member function. And the compiler doesn't resolve it is because in your particular situation, it assumes you've made a mistake and doesn't realize you intended to call the sqrt in lang.Math.

Sepulchritude
+1  A: 

That's quite normal. By writing this code, you didn't overload the Math.sqrt method in any way, you simply defined a Test.sqrt(int) as an argument.

Then there is the question of your error message.

When defining the Test.sqrt method, you overload (in this class) the static import you made.

So, when calling sqrt(1.0 * n), the compiler consider you try to call Test.sqrt(int) with a double, swhich is obviously not possible.

Riduidel