【问题标题】:Overloading of Math.sqrt : overloading method seems to hide the original oneMath.sqrt 的重载:重载方法似乎隐藏了原来的方法
【发布时间】:2011-01-17 20:43:03
【问题描述】:

试图为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

所以问题是:

  1. 为什么编译器无法解决第一种情况下的重载问题?
  2. Java 语言规范中在哪里指定了此行为?

提前致谢。

【问题讨论】:

  • 严格来说,这里并没有重载任何方法。

标签: java static methods overloading


【解决方案1】:

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

如果您想调用 Math.sqrt,请用不同的名称重命名您的函数:

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

【讨论】:

  • 的直接跳过静态导入并使用Math.sqrt()
【解决方案2】:

这很正常。 通过编写此代码,您不会以任何方式重载 Math.sqrt 方法,您只需将 Test.sqrt(int) 定义为参数。

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

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

所以,当调用 sqrt(1.0 * n) 时,编译器会认为你尝试使用 double 调用 Test.sqrt(int),这显然是不可能的。

【讨论】:

    【解决方案3】:

    您只能重载同一类中的方法。 IE。如果你导入另一个类的静态方法,然后用相同的名称定义你自己的方法,将不会有重载决议。该方法的导入版本将被忽略。

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

    如果一个类的两个方法(无论是在同一个类中声明,还是都由一个类继承,或者一个声明一个继承)具有相同的名称但签名不是覆盖等效的,那么方法名称是说是超载了。

    注意它说的是“一个类的两个方法”。所以根本不考虑从另一个类导入的方法。

    因此,由于您的定义不是 Math.sqrt 的重载,因此它会根据 section 6.3.1 of the definition 对其进行遮蔽:

    一个名为 n 的方法的声明 d 遮蔽了任何其他名为 n 的方法的声明,这些方法位于一个封闭范围内 d 在整个 d 范围内出现的点。

    【讨论】:

    【解决方案4】:

    您实际上并没有超载。事情因模棱两可而悬而未决;编译器看到return sqrt(1.0 * n);,它假定您正在谈论Test 类中的sqrt(int) 函数,而不是lang.Math 中的函数。这是更可取的行为;毕竟,您可能不想在每次尝试调用成员函数时都指定class.method。并且编译器无法解决它是因为在您的特定情况下,它假定您犯了一个错误并且没有意识到您打算在lang.Math 中调用sqrt

    【讨论】:

      【解决方案5】:

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

      但在第二次调用中,您指的是 Math.sqrt(),它工作正常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-30
        • 1970-01-01
        • 2010-09-30
        • 2013-05-08
        相关资源
        最近更新 更多