Ответ 1
Как сообщает @Voo,
ваш вопрос о вызове виртуального метода на уже полностью построенный объект. Известные падения вызовов виртуальные методы на построенном объекте хорошо известны, но не применимо здесь
Из Эффективное Java 2nd Edition, пункт 17: Дизайн и документ для наследования, а также запретить его:
Есть еще несколько ограничений, которые должен соблюдать класс для разрешения наследование. Конструкторы не должны вызывать переопределяемые методы, прямо или косвенно. Если вы нарушите это правило, отказ программы будет результат. Конструктор суперкласса выполняется перед подклассом конструктор, поэтому будет задействован метод переопределения в подклассе перед запуском конструктора подкласса. Если метод переопределения зависит от любой инициализации, выполняемой конструктором подкласса, метод не будет вести себя так, как ожидалось.
Вызов переопределяемого метода при построении объекта может привести к использованию неинициализированных данных, что приведет к исключениям во время выполнения или непредвиденным результатам.
Конструкторы должны вызывать только те методы, которые являются окончательными или частными
Вы можете использовать статические методы factory, чтобы исправить проблему, с которой вам нужно создавать свои объекты из Bar class
.
Эффективная Java, пункт 1: рассмотрим статические методы factory вместо конструкторов
Обычный способ для класса позволить клиенту получить экземпляр сам должен предоставить публичный конструктор. Существует еще одна техника это должно быть частью каждого инструментария для программистов. Класс может предоставить публичный статический метод factory, который является просто статическим метод, возвращающий экземпляр класса.
Итак, вы идете иметь интерфейс:
public interface Foo {
void doFoo();
}
и реализация:
public class FooImpl implements Foo {
@Override
public void doFoo() {
//.. Do important code
}
}
Чтобы создать свой класс с помощью метода factory, вы можете работать следующим образом:
-
Используйте интерфейс, чтобы определить переменную вашего класса
private Foo fi
вместоprivate FooImpl fi
, используя интерфейсы над конкретными типами, является ключом к хорошему инкапсуляции и ослаблению связи вашего кода. -
Сделайте свой конструктор по умолчанию закрытым, чтобы предотвратить создание экземпляра вашего класса за пределами.
private Bar() { // Запрещает создание экземпляра }
-
Удалите все вызовы для переопределения методов, присутствующих в вашем конструкторе.
-
Создайте свой статический метод factory
Наконец, вы получите класс Bar
с помощью метода factory, например:
public class Bar {
private Foo fi;
private Bar() {// Prevents instantiation
fi = new FooImpl();
}
public static Bar createBar() {
Bar newBar = new Bar();
newBar.fi.doFoo();
return newBar;
}
}
Мой босс говорит: "Предупреждения сонара касаются симптомов, а не болезни. Лучше всего, когда вы можете лечить болезнь".