Этот вопрос является продолжением: Почему я не могу вызвать метод вне анонимного одноименного класса
Этот предыдущий вопрос отвечает Почему, но теперь я хочу знать, найдет ли javac должен запуск (int bar)? (См. Предыдущий вопрос, чтобы узнать, почему выполнить (42) не удается)
Если нет, то это из-за спецификации? Создает ли он неоднозначный код? Я считаю, что это ошибка. В то время как предыдущий вопрос объяснял, почему этот код не компилируется, я считаю, что он должен компилироваться, если javac выполняет поиск выше в дереве, если ему не удается найти совпадение на текущем уровне. IE. Если this.run () не соответствует, он должен автоматически проверять NotApplicable.this на наличие метода запуска.
Также обратите внимание, что foo (int bar) находится правильно. Если вы укажете какую-либо причину, по которой run (int bar) не должен быть найден, он также должен объяснить, почему найден foo (int bar).
public class NotApplicable {
public NotApplicable() {
new Runnable() {
public void run() {
// this works just fine, it automatically used NotApplicable.this when it couldn't find this.foo
foo(42);
// this fails to compile, javac find this.run(), and it does not match
run(42);
// to force javac to find run(int bar) you must use the following
//NotApplicable.this.run(42);
}
};
}
private void run(int bar) {
}
public void foo(int bar) {
}
}




Для меня это похоже на рецепт двусмысленности и хрупкости - как только новый метод добавляется в ваш базовый класс (ладно, это не так вероятно для интерфейса ...), смысл вашего кода полностью меняется.
Анонимные классы уже довольно уродливы - такая явная деталь меня совсем не беспокоит.
Это правда. Ба, это все ужасный беспорядок. Дайте мне правильное закрытие :)
Такое поведение javac соответствует спецификации. См. §15.12 Выражения вызова метода в Спецификации языка Java, особенно абзац под «Шагом времени компиляции 1», объясняющий значение неквалифицированного вызова метода:
If the Identifier appears within the scope (§6.3) of a visible method declaration with that name, then there must be an enclosing type declaration of which that method is a member. Let T be the innermost such type declaration. The class or interface to search is T.
Другими словами, неквалифицированный метод имя ищется во всех охватывающих областях, а самое внутреннее «объявление типа» (что означает либо объявление класса, либо объявление интерфейса), в котором найдено имя, будет поиском всего подпись (в «Шаге 2 на этапе компиляции»).
Спасибо, я думаю, что понимаю спецификацию. Теперь я могу утверждать, что это плохая спецификация и ее следует изменить. Шаг 1 времени компиляции должен включать в себя включающий класс анонимного класса.
Пытаться
NotApplicable.this.run(42);
вместо.
Обратите внимание, что в то время, когда я писал этот ответ, комментарий с тем же фрагментом кода в нем не присутствовал в вопросе.
Хорошо, тогда почему javac разрешено находить foo (int bar)? Рецепт тот же.