Я помню, как пару лет назад я использовал статические инициализаторы для вызова операций установки уровня класса. Я помню, что это было очень странное поведение, и я просто решил уйти от них. Возможно, это было из-за того, что я испортил верхний заказ или был новичком. Но я сталкиваюсь с необходимостью пересмотреть их, и я хочу убедиться, что нет лучшего способа, который будет столь же кратким.Легитимное использование для статического инициализатора?
Я знаю, что это не модно, но у меня часто есть классы, управляемые данными, которые поддерживают статический список экземпляров, импортированных из базы данных.
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
}
Когда у меня есть десятки табличных классов, как эта, эта картина очень краткая (да, я знаю, что плотна пару класса с одним источником данных/экземпляров).
Однако, когда я обнаружил доброту Google Guava, я хочу использовать EventBus для обновления статического списка при отправке определенного события. Я бы создал статическую конечную логическую переменную, чтобы вызвать статический метод, который инициализировал регистрацию.
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
private static final boolean subscribed = subscribe();
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
private static boolean subscribe() {
MyEventBus.get().register(new Object() {
@Subscribe
public void refresh(ParameterRefreshEvent e) {
stratBands = importFromDb();
}
});
return true;
}
}
Это получило раздражает очень быстро, потому что компилятор будет бросать предупреждения над подписного переменной никогда не используется. Кроме того, он просто добавил беспорядок. Поэтому мне интересно, не кошерно ли использовать статический инициализатор, и там действительно нет лучшего способа, если я не отделяю его от двух или более классов. Мысли?
public class StratBand {
private static volatile ImmutableList<StratBand> stratBands = importFromDb();
static {
MyEventBus.get().register(new Object() {
@Subscribe
public void refresh(ParameterRefreshEvent e) {
stratBands = importFromDb();
}
});
}
private final int minRange;
private final int maxRange;
private static ImmutableList<StratBand> importFromDb() {
//construct list from database here
}
//constructors, methods, etc
}
Это «не модно» именно потому, что, как вы обнаружили, это приводит к «очень странным поведением». Как правило, лучше не ставить вещи вообще, передавать их там, где они необходимы явно (или неявно с инъекцией зависимостей). Статические инициализаторы прекрасны, когда они просто создают синглтоны или выполняют чистое вычисление, но на самом деле они вообще не должны взаимодействовать с файловой системой, базами данных или чем-либо снаружи. –
Я ждал, чтобы кто-то сказал это. И я получаю парадигму DI, которую я ценю. Но пока мы не будем готовы расширять рамки, основанные на DI, я как бы надеюсь сохранить то, что у нас есть немного дольше. – tmn
Вам здесь не нужно использовать DI, но я был бы удивлен, если бы вы могли заставить это работать вообще, и он будет оставаться очень хрупким, трудным для тестирования, и, откровенно говоря, это потребует больше усилий, чем делать это правильно взял бы. –