Вызовы методов занимают довольно большую часть спецификации.Таким образом, компилятор выполняет следующие действия:
- Идентифицирует классы, для которых может быть вызван метод.
- Идентифицирует методы в тех классах, которые могут быть вызваны.
- Если было идентифицировано более одного метода, выберите наиболее конкретный.
Шаг 2 является наиболее интересным здесь: он выполняется в несколько этапов.Подводя итог:
- Если в классе есть метод не-varargs с точно такими же типами параметров (строгий вызов), выберите его.
- Если есть не-varargsвыберите метод класса с типами параметров, для которых автоматическое преобразование из фактических параметров (свободный вызов) выберите.
- Если в классе есть метод varargs с типами параметров, которые соответствуют автоматическому преобразованию, выберите его.
Вы предоставляете параметры, которые точно не соответствуют ни одному из типов параметров перегрузок, поэтому вам необходимо проверить, можете ли вы преобразовать эти параметры, чтобы разрешить строгий вызов.Преобразования в строгих вызовах являются :
- преобразованием идентичности (§5.1.1)
- преобразованием растущего примитива (§5.1.2)
- расширяющее эталонное преобразование (§5.1.5)
. int
можно преобразовать путем преобразования идентификаторов в int
.long
можно преобразовать с помощью расширяющегося примитивного преобразования в float
.
Следовательно, применимо f(int, float)
.
f(long, double)
и f(double, double)
являютсятакже применимо, поскольку int
может быть расширен до long
и double
;и long
может быть расширен до double
.
Однако они менее специфичны, чем f(int, float)
, поскольку int
может быть расширен до long
и double
, а float
можетбыть расширен до double
.Следовательно, согласно неформальной интуиции , изложенной в JLS Sec 15.12.2.5 , эти методы менее специфичны, чем f(int, float)
.Таким образом, f(int, float)
- это тот, который вызывается.