Geschichte der Frage
Von Anfang an wurde Java als objektorientierte Sprache entwickelt, bei der die Hauptaufgabe durch das Erstellen von Klasseninstanzen gelöst wurde. Für häufig verwendete Methoden (z.B. Sortierung, Datenumwandlung) wurden jedoch Utility-Klassen mit einer Sammlung statischer Methoden (z.B. java.util.Collections) eingeführt.
Problem
Statische Methoden erleichtern den Aufruf von Hilfsfunktionen, sind jedoch nicht geeignet, um den Zustand zu speichern, Abhängigkeiten zu injecten und isoliert zu testen. Andererseits sind Klasseninstanzen flexibler, erhöhen jedoch die Code-Menge für die Initialisierung und erfordern einen durchdachten Lebenszyklus.
Lösung
Utility-Klassen (Utility-Klassen) — eine Sammlung statischer, zustandsloser Methoden, die keine Objektinstanziierung erfordern. Gut für Manipulationen mit Sammlungen, Umwandlungen und mathematische Operationen.
Instanzen von Klassen — speichern Zustand, verwenden Abhängigkeiten, bieten Erweiterbarkeit und Testbarkeit. Werden in der Geschäftslogik, Diensten, Controllern usw. verwendet.
Beispielcode:
// Beispiel für eine Utility-Klasse public class MathUtils { public static int add(int a, int b) { return a + b; } } // Verwendung: int sum = MathUtils.add(1, 2); // Beispiel für eine Klasseninstanz für Geschäftslogik public class OrderService { private final OrderRepository repo; public OrderService(OrderRepository repo) { this.repo = repo; } public void placeOrder(Order o) { repo.save(o); } }
Wesentliche Merkmale:
Kann man Utility-Klassen erben und deren statische Methoden erweitern?
Nein, normalerweise werden Utility-Klassen als final deklariert, mit einem privaten Konstruktor. Die Vererbung von statischen Methoden ist möglich, macht jedoch wenig Sinn, da statische Methoden nicht auf Instanzebene geerbt werden.
Beispielcode:
public final class MyUtils { private MyUtils() {} // verhindert die Instanziierung }
Können Utility-Klassen Zustand enthalten?
Nein. Wenn eine Utility-Klasse Zustand enthält (Instanz- oder statische Felder), verletzt dies das Prinzip des Schreibens von Utilities, führt zu Multithreading-Problemen und verringert die Lesbarkeit.
Kann man statische Methoden von Utility-Klassen beim Testen mocken?
Nur mit speziellen Tools wie PowerMock, die Tests komplexer und manchmal instabil machen. In der Regel ist ein DI-freundlicher Ansatz mit Instanzen für Tests vorzuziehen.
In einem Projekt sind alle Dienste mit statischen Utility-Methoden implementiert. Dependency Injection ist unmöglich, Unit-Tests sind nicht isoliert, jeder Test ist von einem Zustand der Umgebung abhängig.
Vorteile:
Nachteile:
In den Diensten werden separate Klassen mit Dependency Injection über Schnittstellen verwendet. Für Umwandlungen und einfache Operationen werden separate zustandslose Utility-Klassen verwendet.
Vorteile:
Nachteile: