Ich erinnere mich, dass ich vor ein paar Jahren statische Initialisierer verwendet habe, um Setup-Operationen auf Klassenebene aufzurufen. Ich erinnere mich daran, dass ich sehr bizarre Verhaltensweisen hatte und ich beschloss einfach, mich von ihnen fern zu halten. Vielleicht lag es daran, dass ich die Bestellung von oben nach unten durcheinander brachte oder ein Neuling war. Aber ich stoße auf die Notwendigkeit, sie noch einmal zu besuchen, und ich möchte sicherstellen, dass es keinen besseren Weg gibt, der ebenso prägnant ist.Legitime Verwendung für statische Initialisierung?
Ich weiß, dass es nicht modisch ist, aber ich habe oft datengesteuerte Klassen, die eine statische Liste von Instanzen verwalten, die aus einer Datenbank importiert werden.
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
}
Wenn ich Dutzende von tabellengesteuerten Klassen wie diese haben, ist dieses Muster sehr prägnant (ja, ich weiß, dass es eng koppelt die Klasse mit einer Datenquelle/Instanzen).
Als ich jedoch die Güte von Google Guava entdeckte, möchte ich den EventBus verwenden, um die statische Liste zu aktualisieren, wenn ein bestimmtes Ereignis gepostet wurde. Ich würde eine statische finale boolesche Variable erstellen, nur um eine statische Methode aufzurufen, die die Registrierung initialisiert hat.
Dies wurde sehr schnell nervig, weil der Compiler würde Warnungen über die abonnierte Variable nie verwendet werden. Außerdem fügte es einfach Unordnung hinzu. Ich frage mich, ob es koscher ist, den statischen Initialisierer zu verwenden, und es gibt wirklich keinen besseren Weg, wenn ich das nicht in zwei oder mehr Klassen entkopple. Gedanken?
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
}
Es ist "nicht modisch", weil es, wie Sie herausgefunden haben, zu "sehr bizarren Verhaltensweisen" führt. Es ist im Allgemeinen eine bessere Praktik, diese Dinge überhaupt nicht statisch zu haben, um sie dort zu übergeben, wo sie explizit benötigt werden (oder implizit durch die Abhängigkeitsinjektion). Statische Initialisierer sind in Ordnung, wenn sie nur Singletons erstellen oder reine Berechnungen durchführen, aber sie sollten im Allgemeinen nicht mit dem Dateisystem, Datenbanken oder irgendetwas anderem interagieren. –
Ich habe darauf gewartet, dass jemand das sagt. Und ich bekomme das DI-Paradigma, das ich schätze. Aber bis wir bereit sind, auf ein DI-gestütztes Framework hochzuskalieren, hoffe ich, dass wir etwas länger halten können. – tmn
Sie müssen DI hier nicht verwenden, aber ich wäre überrascht, wenn Sie dies überhaupt zur Arbeit bringen könnten, und es wird äußerst fragil bleiben, schwer zu testen sein, und ehrlich gesagt würde es mehr Aufwand erfordern, als es richtig zu machen würde nehmen. –