Java 重载Math.sqrt:重载方法似乎隐藏了原始方法

Java 重载Math.sqrt:重载方法似乎隐藏了原始方法,java,static,methods,overloading,Java,Static,Methods,Overloading,正在尝试为int类型重载java.lang.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)

正在尝试为
int
类型重载
java.lang.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

因此,问题是:

  • 为什么编译器不能在第一种情况下解决重载问题
  • java语言规范中在哪里指定了这种行为
  • 提前感谢。

    是的,
    Test中的sqrt(int)不能应用于(double)

    如果要调用Math.sqrt,请使用其他名称重命名函数:

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

    只能重载同一类中的方法。也就是说,如果导入另一个类的静态方法,然后用相同的名称定义自己的方法,则不会出现重载解析。方法的导入版本将被忽略

    关于指定此行为的位置:语言规范定义了重载:

    如果一个类的两个方法(无论是在同一个类中声明的,还是都由一个类继承的,或者一个声明的和一个继承的)具有相同的名称,但签名不是重写等价的,则称该方法名为重载

    请注意,它表示“一个类的两个方法”。因此,根本不考虑从另一个类导入的方法

    因此,由于您的定义不是Math.sqrt的重载,因此它会按照以下方式对其进行阴影处理:

    名为n的方法的声明d在d在整个d范围内出现的点处,隐藏了封闭范围内名为n的任何其他方法的声明


    在第一个调用中,所引用的方法是您返回的方法,该方法期望int作为其参数,但您正在向其发送double。所以它给出了一个编译器错误


    但是在第二个调用中,您指的是Math.sqrt(),它工作得很好。

    您实际上并没有重载。事情因模棱两可而悬而未决;编译器看到
    返回sqrt(1.0*n)
    ,它假定您正在谈论类
    测试中的
    sqrt(int)
    函数,而不是
    lang.Math
    中的函数。这是更好的行为;毕竟,您可能不希望每次尝试调用成员函数时都必须指定
    class.method
    。编译器没有解决这个问题,因为在您的特定情况下,它假设您犯了错误,并且没有意识到您打算在
    lang.Math
    中调用
    sqrt
    ,这很正常。 通过编写此代码,您没有以任何方式重载
    Math.sqrt
    方法,您只是将
    Test.sqrt(int)
    定义为一个参数

    然后是你的错误信息的问题

    定义Test.sqrt方法时,会重载(在此类中)所做的静态导入


    这样,当调用SqRT(1 *N)时,编译器会尝试调用一个加倍的Stest.qrt(int),这显然是不可能的。

    严格地说,这里没有超载任何方法。这个行为在类方法的一节中被描述。@ TunIO:您的链接是关于覆盖与隐藏的关系,与重载和阴影相反,这是这里的问题。感谢您的澄清和指向java规范的正确链接!当然,只需跳过静态导入并使用
    Math.sqrt()