Ниже приведен пример из JLS 15.13.1:
Пример двусмысленности:
Код: Выделить всё
interface Fun { R apply(T arg); }
class C {
int size() { return 0; }
static int size(Object arg) { return 0; }
void test() {
Fun f1 = C::size;
// Error: instance method size()
// or static method size(Object)?
}
}
Согласно JLS 15.13.1( Сохраните соответствующие части.):
• Сначала определяется тип для поиска:
– Если метод ссылочное выражение имеет вид
Код: Выделить всё
ReferenceType ::[TypeArguments] Identifierпреобразования захвата (§5.1.10), примененного к ReferenceType.
Таким образом, Типом для поиска является тип класса C.
• Во-вторых, для заданного типа целевой функции с n параметрами набор Идентифицированы
потенциально применимые методы:
– если выражение ссылки на метод имеет форму
Код: Выделить всё
ReferenceType :: [TypeArguments] Identifierто потенциально применимые методы:
› методы-члены типа для поиска, который будет потенциально
применимо (§15.12.2.1) для вызова метода, имя которого
Идентификатор, имеет разрядность n, имеет аргументы типа TypeArguments и появляется
в том же классе в качестве выражения ссылки на метод; плюс
› методы-члены искомого типа, которые потенциально
применимы для вызова метода с именем Identifier, имеющего арность
Код: Выделить всё
n-1, что и выражение ссылки на метод.
Таким образом, методы имеют размер int () и int size(Object arg) все потенциально применимы.
(Правила потенциально применимые также требуют, чтобы параметры и аргументы были потенциально совместимыми. Нет ли в этом необходимости, поскольку типы аргументов для вызова не упоминаются?)
• Наконец, если нет потенциально применимых методов, то
нет и объявления во время компиляции.
В противном случае, учитывая целевой тип функции
с типами параметров P1, ..., Pn и набор потенциально
применимых методов, объявление времени компиляции выбирается какследует:
– Если выражение ссылки на метод имеет форму
Код: Выделить всё
ReferenceType ::[TypeArguments] Identifierприменимого метода. Каждый поиск описан в
§15.12.2.2 – §15.12.2.5, с пояснениями ниже. Каждый
поиск создает набор применимых методов и, возможно, определяет
наиболее конкретный метод из этого набора. В случае ошибки, указанной в §15.12.2.4, набор применимых методов пуст. В
в случае ошибки, указанной в §15.12.2.5, не существует наиболее
специфического метода.
При первом поиске обрабатывается ссылка на метод. как если бы это был
вызов с выражениями аргументов типов P1, ..., Pn. Аргументы типа
, если таковые имеются, задаются выражением ссылки на метод.
Во втором поиске, если P1, ..., Pn не пусто и P1 является подтипом
ReferenceType, тогда выражение ссылки на метод рассматривается как
если бы оно было выражением вызова метода с выражениями аргументов
типов P2, ..., Pn . Если ReferenceType является необработанным типом и существует
параметризация этого типа, G, которая является супертипом P1,
типа для поиска. является результатом преобразования захвата (§5.1.10), примененного
к G; в противном случае тип поиска будет таким же, как тип
первого поиска. Аргументы типа, если таковые имеются, передаются с помощью
ссылочного выражения.
Если первый поиск дает наиболее конкретный метод, который является статическим,
и набор применимые методы, полученные в результате второго поиска,
не содержат нестатических методов, то объявление времени компиляции является
наиболее конкретным методом первого поиска.
Это место меня больше всего смущает.
Тип параметра типа целевой функции (кажется, я не видел соответствующего термина. Мой понимание заключается в том, что это тип функции функционального интерфейса) — C.
При первом поиске выражение ссылки на метод обрабатывается как вызов с выражением аргумента введите C.
Затем, на основе параметров двух методов размера, после процесса проверки от Строгого вызова до Выбора наиболее конкретного метода остался только один метод:
Код: Выделить всё
static int size(Object arg)Во втором поиске выражение ссылки на метод рассматривается как вызов метода без каких-либо выражений аргументов. Таким образом, только int size() метод остается.
Если первый поиск дает наиболее конкретный метод, который является статическим,
и создается набор применимых методов при втором поиске
не содержит нестатических методов, то объявление времени компиляции является
наиболее конкретным методом первого поиска.
Итак, объявление времени компиляции — это статический метод int size(Object arg).
Я не понимаю, почему здесь возникла ошибка. Я также не совсем уверен, есть ли проблемы с моим анализом. Не могли бы вы предоставить конкретное содержание спецификации, чтобы объяснить проблему с этим кодом?
Кроме того, согласно моему анализу, я также не могу понять следующее содержание этого примера кода:
Эту двусмысленность нельзя разрешить, предоставив применимый экземпляр
метода, который более специфичен, чем применимый статический метод:..
(JLS 15.13.1)
Есть ли кто-нибудь, кто мог бы объяснить мне эту часть подробно?
Спасибо, что прочитали и ответили.
Подробнее здесь: https://stackoverflow.com/questions/791 ... ce-illegal
Мобильная версия