Статический импорт не работает, когда у класса есть методы с тем же именем, что и импортированные

У меня есть Junit4 тестовый случай, который статически импортирует org.junit.Assert.assertEquals Способ (ы).

import static org.junit.Assert.assertEquals;

В этом классе я создал вспомогательный метод для утверждения некоторых сложных внутренних классов, которые не реализуют равенства (а также испытывают трудности при его реализации).

private void assertEquals(MyObj o1, MyObj o2)
{
    assertEquals(o1.getSomething(), o2.getSomething());
    assertEquals(o1.getSomethingElse(), o2.getSomethingElse());
    ...
}

Я ожидал, что код будет вести себя так, как будто я "перегружаю" assertEquals метод (ы), который я импортирую, но похоже, что мой частный нестатический метод скрывает статически импортированные методы. Я также попытался превратить мой метод в public а также static (все перестановки), но безуспешно - мне пришлось его переименовать.

Есть причина, по которой он так себя ведет? Я не смог найти ссылки на это поведение в документации.

4 ответа

Решение

То, что вы заметили, называется Shadowing. Когда два типа в Java имеют одно и то же простое имя, один из них будет затенять другой. затем затененный тип не может использоваться его простым именем.

Наиболее распространенный тип теневого копирования - это параметр для скрытия поля. обычно приводит к тому, что код установки выглядит setMyInt(int myInt) {this.myInt = myInt; }

Теперь давайте прочитаем соответствующую документацию:

Объявление static-import-on-demand никогда не приводит к затенению любого другого объявления.

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

Перегрузка и перезапись работает в дереве наследования. Но статический импорт не создает наследство.

Если вы хотите использовать assertEquals из junit в своем собственном методе assertEquals, вы должны квалифицировать его с помощью className, например, Assert.assertEquals.

Используйте нестатический импорт org.junit.Assert.

Вы наткнулись на скрытие метода, где присутствие локального метода "скрывает" один от другого класса (часто суперкласса).

Я всегда чувствовал, что статически импортируемые методы, хотя и синтаксически возможны, как-то "неправильны".

Как стиль я предпочитаю импортировать класс и использовать TheirClass.method() в моем коде. Это дает понять, что метод не является локальным методом, и одним из отличительных признаков хорошего кода является ясность.

я советую тебе import org.junit.Assert и использовать Assert.assertEquals(...),

Это имеет смысл. Предположим, что Javac делает то, что вы хотите, он выбирает ваш assertEquals(MyObj, MyObj) метод сегодня. Что если завтра org.junit.Assert добавляет свой собственный assertEquals(MyObj, MyObj) метод? Значение вызова assertEquals(mo1,mo2) резко изменилась, не зная об этом.

На вопрос, значение слова assertEquals, Javac должен решить, что это название метода (ов) в org.junit.Assert, Только после этого он может выполнить разрешение перегрузки методов: изучить все методы в org.junit.Assert с именем assertEqualsвыберите наиболее подходящий.

Вполне возможно, что java может справиться с перегрузкой методов из нескольких классов, однако, как показывает первый абзац, это вызывает большую неопределенность у разработчика, к какому классу он вызывает метод. Поскольку эти классы не связаны, семантика метода может сильно отличаться.

Если во время компиляции нет никаких сомнений в том, что разработчик принадлежит к какому классу принадлежит метод, все еще возможно, что класс перегрузит метод завтра, поэтому изменив вызываемый целевой метод. Однако, поскольку это делается одним и тем же классом, мы можем считать его ответственным. Например, если org.junit.Assert решает добавить новый assertEquals(MyObj, MyObj) метод, он должен знать, что некоторые предыдущие вызовы assertEquals(Object,Object) теперь перенаправлены на новый метод, и он должен убедиться, что нет изменений семантики, которые нарушат сайты вызовов.

Другие вопросы по тегам