Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading of Math.sqrt : overloading method seems to hide the original one

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.

like image 346
Pragmateek Avatar asked Feb 17 '10 13:02

Pragmateek


4 Answers

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.

like image 21
Riduidel Avatar answered Nov 11 '22 05:11

Riduidel


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.

like image 134
sepp2k Avatar answered Nov 11 '22 06:11

sepp2k


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.

like image 32
Sepulchritude Avatar answered Nov 11 '22 06:11

Sepulchritude


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

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

private static double mysqrt(int n)
{
    return sqrt(1.0 * n);
}
like image 28
Igor Artamonov Avatar answered Nov 11 '22 06:11

Igor Artamonov