попытка перегрузиться 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.
Таким образом, вопросы:
Заранее спасибо.
Вы можете только методы перегрузки в том же классе. Т.е. если вы импортируете статический метод другого класса, а затем определите свой собственный метод с тем же именем, разрешения перегрузки не будет. Импортированная версия метода будет просто проигнорирована.
Относительно того, где указано это поведение: спецификация языка определяет перегрузку следующим образом :
Если два метода класса (объявлены ли оба в одном классе или оба унаследованы классом, или один объявленный и один унаследованный) имеют одно и то же имя, но сигнатуры не эквивалентны переопределению, тогда имя метода называется перегруженным.
Обратите внимание, что там написано «два метода класса». Поэтому методы, импортированные из другого класса, просто не рассматриваются.
Так как ваше определение не является перегрузкой Math.sqrt, оно затеняет его согласно раздел 6.3.1 определения :
Объявление d метода с именем n затеняет объявления любые другие методы с именем n, которые находятся во включающей области видимости в точке, где d встречается во всей области видимости d.
На самом деле вы не перегружаетесь. Вещи зацикливаются на двусмысленности; компилятор видит return sqrt (1.0 * n);
, он предполагает, что вы говорите о функции sqrt (int)
в классе Test
, а не о том в lang.Math
. Это предпочтительное поведение; в конце концов, вы, вероятно, не захотите указывать class.method
каждый раз, когда вы пытаетесь вызвать функцию-член. И компилятор не разрешает это, потому что в вашей конкретной ситуации он предполагает, что вы допустили ошибку, и не понимает, что вы намеревались вызвать sqrt
в lang.Math
.
В первом вызове метод, на который вы ссылаетесь, это тот, который вы вернули, который ожидает int в качестве параметра, но вы посылаете ему double. поэтому он выдает ошибку компилятора.
Но во втором вызове вы ссылаетесь на Math.sqrt(), который работает нормально.
Да, sqrt(int) в Test не может быть применен к (double)
Переименуйте вашу функцию другим именем, если вы хотите вызвать Math.sqrt:
private static double mysqrt(int n)
{
return sqrt(1.0 * n);
}
Это вполне нормально.
Написав этот код, вы никак не перегрузили метод Math.sqrt
, вы просто определили Test.sqrt(int)
в качестве аргумента.
Тогда возникает вопрос о вашем сообщении об ошибке.
При определении метода Test.sqrt вы перегружаете (в этом классе) сделанный вами статический импорт.
Поэтому при вызове sqrt(1.0 * n) компилятор считает, что вы пытаетесь вызвать Test.sqrt(int) с двойкой, что, очевидно, невозможно.