Перегрузка Math.sqrt: перегрузка метода, кажется, скрывает исходный

попытка перегрузиться java.lang.Math.sqrt статический метод для int тип:

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?

Заранее спасибо.

9
задан Joachim Sauer 17 February 2010 в 13:21
поделиться

5 ответов

Вы можете только методы перегрузки в том же классе. Т.е. если вы импортируете статический метод другого класса, а затем определите свой собственный метод с тем же именем, разрешения перегрузки не будет. Импортированная версия метода будет просто проигнорирована.

Относительно того, где указано это поведение: спецификация языка определяет перегрузку следующим образом :

Если два метода класса (объявлены ли оба в одном классе или оба унаследованы классом, или один объявленный и один унаследованный) имеют одно и то же имя, но сигнатуры не эквивалентны переопределению, тогда имя метода называется перегруженным.

Обратите внимание, что там написано «два метода класса». Поэтому методы, импортированные из другого класса, просто не рассматриваются.

Так как ваше определение не является перегрузкой Math.sqrt, оно затеняет его согласно раздел 6.3.1 определения :

Объявление d метода с именем n затеняет объявления любые другие методы с именем n, которые находятся во включающей области видимости в точке, где d встречается во всей области видимости d.

13
ответ дан 4 December 2019 в 11:04
поделиться

На самом деле вы не перегружаетесь. Вещи зацикливаются на двусмысленности; компилятор видит return sqrt (1.0 * n); , он предполагает, что вы говорите о функции sqrt (int) в классе Test , а не о том в lang.Math . Это предпочтительное поведение; в конце концов, вы, вероятно, не захотите указывать class.method каждый раз, когда вы пытаетесь вызвать функцию-член. И компилятор не разрешает это, потому что в вашей конкретной ситуации он предполагает, что вы допустили ошибку, и не понимает, что вы намеревались вызвать sqrt в lang.Math .

2
ответ дан 4 December 2019 в 11:04
поделиться

В первом вызове метод, на который вы ссылаетесь, это тот, который вы вернули, который ожидает int в качестве параметра, но вы посылаете ему double. поэтому он выдает ошибку компилятора.

Но во втором вызове вы ссылаетесь на Math.sqrt(), который работает нормально.

0
ответ дан 4 December 2019 в 11:04
поделиться

Да, sqrt(int) в Test не может быть применен к (double)

Переименуйте вашу функцию другим именем, если вы хотите вызвать Math.sqrt:

private static double mysqrt(int n)
{
    return sqrt(1.0 * n);
}
1
ответ дан 4 December 2019 в 11:04
поделиться

Это вполне нормально. Написав этот код, вы никак не перегрузили метод Math.sqrt, вы просто определили Test.sqrt(int) в качестве аргумента.

Тогда возникает вопрос о вашем сообщении об ошибке.

При определении метода Test.sqrt вы перегружаете (в этом классе) сделанный вами статический импорт.

Поэтому при вызове sqrt(1.0 * n) компилятор считает, что вы пытаетесь вызвать Test.sqrt(int) с двойкой, что, очевидно, невозможно.

3
ответ дан 4 December 2019 в 11:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: