Best Practice für Java: Klasse mit nur statischen Methoden

Lesezeit: 7 Minuten

Benutzer-Avatar
Benutzer3629892

Ich habe eine Anwendung, in der ich eine Klasse namens habe PlausibilityChecker. Diese Klasse hat nur statische Methoden, wie z checkZipcodeFormat oder checkMailFormat. Ich verwende sie in meinen GUI-Klassen, um die Eingabe zu überprüfen, bevor ich sie an die untere Schicht sende.

Ist das eine gute Praxis? Ich dachte, ich würde nur statische Methoden verwenden, damit ich mich nicht darum kümmern muss, eine Instanz an die GUI-Klassen zu übergeben oder ein Instanzfeld in jeder GUI-Klasse zu haben, das nicht auf ein GUI-Objekt verweist.

Mir ist aufgefallen, dass die Files Klasse von Java NIO hat nur statische Methoden, also nehme ich an, dass das nicht so schrecklich falsch sein kann.

  • Solange es keinen Status hat, ist alles in Ordnung.

    – Sotirios Delimanolis

    14. Juli 2015 um 14:48 Uhr

  • Statische Klassen sind in Ordnung, vergessen Sie nur nicht, einen privaten Konstruktor hinzuzufügen. Ah, und achten Sie auf Multi-Threading-Zugriffe.

    – m0skit0

    14. Juli 2015 um 14:49 Uhr


  • Geben Sie weitere Informationen über die Struktur Ihres Programms an.

    – Marun

    14. Juli 2015 um 14:50 Uhr

  • Wir nennen solche Klassen normalerweise *Helper. Es ist nichts Falsches daran, solche zu haben. Extra private constuctor() kann die Instanziierung verhindern,

    – Todesengel908

    14. Juli 2015 um 14:51 Uhr

  • Ich habe es auch oft mit dem Namen “Utility” gesehen

    – DoppeltDoppelt

    14. Juli 2015 um 14:51 Uhr


Benutzer-Avatar
Luiggi Mendoza

Ich würde sagen, du machst es richtig. Abgesehen davon einige Ratschläge für Ihre Gebrauchsklasse:

  • Stellen Sie sicher, dass es keinen Zustand hat. Das heißt, es gibt kein Feld in der Klasse, es sei denn, es ist deklariert static final. Stellen Sie außerdem sicher, dass dieses Feld ebenfalls unveränderlich ist, z Strings.
  • Stellen Sie sicher, dass es sich nicht um eine Superklasse anderer Klassen handeln kann. Klasse machen final andere Programmierer können es also nicht erweitern.
  • Dies ist umstritten, aber Sie können einen No-Arg-Konstruktor deklarieren private, sodass keine andere Klasse eine Instanz Ihrer Utility-Klasse erstellen könnte (die Verwendung von Reflektion oder etwas Ähnlichem reicht aus, aber es besteht keine Notwendigkeit, mit der Klasse so beschützend umzugehen). Warum dürfen Sie das nicht? Nun, dies ist der seltsame Fall, in dem Sie eine Instanz der Utility-Klasse einfügen möchten/müssen, z. B. über eine Schnittstelle, anstatt sie direkt in Ihrer Klasse zu verwenden. Hier ist ein Beispiel dafür. Dieses Design ist wirklich seltsam, kann aber vorkommen (wie im obigen Link gezeigt), aber wenn Sie in einem solchen Fall nicht ausgeführt werden, ist es am besten, den Konstruktor beizubehalten private.

Es gibt viele Bibliotheken, die Hilfsklassen bereitstellen, um uns Programmierern bei unserer Arbeit zu helfen. Einer der bekanntesten ist Apache Common Reihe von Bibliotheken. Es ist Open Source und Sie können den Code überprüfen, um zu sehen, wie sie diese Dienstprogrammklassen entwerfen, um Ihre zu erstellen. (HAFTUNGSAUSSCHLUSS: Ich arbeite oder unterstütze diese Bibliotheken nicht, ich bin ein glücklicher Benutzer von ihnen)

Wichtiger Hinweis: Vermeiden Sie die Verwendung eines Singletons für Ihre Utility-Klasse.

  • Wäre es nicht besser, wenn er Singleton-Muster verwendet und alle Funktionen normal erstellt, außer für getInstance() ?

    – Fehler passieren

    14. Juli 2015 um 14:53 Uhr

  • @BugsHappen verwende kein Singleton, es ist böse.

    – Luiggi Mendoza

    14. Juli 2015 um 14:55 Uhr

  • Für den ersten Aufzählungspunkt ist es meiner Meinung nach nicht ausreichend zu sagen, dass alle Felder statisch final sind, da ein letztes Feld auf etwas Veränderliches verweisen kann. Ich würde sagen, stellen Sie sicher, dass nichts veränderbar ist und dass es keine Abhängigkeiten von irgendetwas Externem gibt (Dateisystem, Datenbank usw.). obwohl das Beispiel von nio Files gegen diesen letzten Teil verstößt.

    – Nathan Hughes

    14. Juli 2015 um 15:02 Uhr


In Java 8 können Sie jetzt Ihre statischen Hilfsklassen in Schnittstellen mit statischen Implementierungen ändern. Dadurch entfällt die Notwendigkeit, die Klasse endgültig zu machen und einen privaten Konstruktor bereitzustellen. Es ist so einfach, „Klasse“ in „Schnittstelle“ zu ändern und das letzte Wort zu entfernen, wenn Sie es haben (alle Schnittstellen sind abstrakt, also können sie nicht endgültig sein). Da Schnittstellenmethoden immer öffentlich sind, können Sie jeden öffentlichen Gültigkeitsbereich von ihnen entfernen. Wenn Sie einen privaten Konstruktor haben, entfernen Sie diesen ebenfalls (Sie können keine Schnittstelle mit einem Konstruktor kompilieren, da sie nicht instanziiert werden können). Es ist weniger Code und sieht sauberer aus. Sie müssen keine Klassen umgestalten, die es bereits verwenden.

  • Auf Sprachniveau ‘7’ werden Erweiterungsmethoden nicht unterstützt. Die statische Schnittstellenmethode erfordert API-Level 24

    – Vahag Chakhoyan

    2. Juli 2019 um 9:27 Uhr


Benutzer-Avatar
Zhong Yu

Machen Sie sich keine Gedanken über Unterklassenbildung oder Instanziierung. Die folgenden Utility-Klassen im JDK können abgeleitet oder instanziiert werden, aber niemand hat sie in all den Jahren missbraucht. Menschen sind es nicht das dumm.

java.beans.Beans
java.beans.PropertyEditorManager
java.lang.invoke.LambdaMetafactory
java.lang.reflect.Modifier
java.net.URLDecoder                                   ...but not URLEncoder:)
javax.management.DefaultLoaderRepository
javax.management.Query
javax.management.loading.DefaultLoaderRepository
javax.management.relation.RoleStatus
javax.print.ServiceUI
javax.swing.UIManager
javax.swing.plaf.basic.BasicBorders
javax.swing.plaf.basic.BasicGraphicsUtils
javax.swing.plaf.basic.BasicHTML
javax.swing.plaf.basic.BasicIconFactory
javax.swing.plaf.metal.MetalBorders
javax.swing.plaf.metal.MetalIconFactory
javax.swing.text.Utilities
javax.swing.text.html.HTML

Als öffentliche API möchten Sie jedoch den Standardkonstruktor unterdrücken, da sonst auf der Javadoc-Seite ein undokumentierter Konstruktor vorhanden ist, der umständlich und verwirrend ist. Für Ihre eigenen internen APIs spielt es keine Rolle, niemand kümmert sich darum.

Es gibt jedoch keinen Grund, Unterklassen zu unterdrücken. Wenn jemand aus irgendeinem Grund eine Utility-Klasse unterteilen möchte, lassen Sie ihn. Natürlich unterdrückt der private Konstruktor als Nebeneffekt die Unterklassenbildung.


In Java8 gibt es mehr Gestaltungsmöglichkeiten zu berücksichtigen –

Eine Schnittstelle mit allen statischen Methoden – das ist genauso gut wie eine Klasse mit allen statischen Methoden. Weder Schnittstelle noch Klasse sind für diesen Zweck konzipiert, also ist beides in Ordnung. Erwarten Sie jedoch nicht, diese statischen Methoden in Subtypen der Schnittstelle zu erben – statische Schnittstellenmethoden sind nicht vererbbar. Ein Pluspunkt für die Verwendung von Interface ist, dass wir nicht unterdrücken müssen, dass der Standardkonstruktor in Javadoc erscheint.

Eine Schnittstelle mit allen Standardmethoden – Zugriff durch Vererbung. Dies ist interessant, aber im Allgemeinen problematisch (die Vererbung funktioniert nur im nicht statischen Kontext). Aber es könnte eine bessere Option in einigen API-Designs sein, zum Beispiel hier HTML-Builder API.

  • Dies widerspricht dem Rat von Joshua Bloch in seinem Buch „Effective Java“, in dem er Ihnen rät, nur Schnittstellen zum Definieren von Typen zu verwenden.

    – Gen

    2. Oktober 2019 um 2:10 Uhr

Warum sollte es keine gute Praxis sein, wenn Sie nur Methoden haben, die anderen Klassen “Werkzeuge” zur Verfügung stellen, das ist in Ordnung.

Singleton sind ok, je nach Kontext.

Zu Testzwecken möchten Sie möglicherweise Verweise auf Singletons verspotten, um Nebenwirkungen während Komponententests zu vermeiden. In diesem Fall ist es wahrscheinlich sinnvoll, ein Dependency-Injection-Framework wie Spring zu verwenden, um die Erstellung der Instanz zu handhaben und reguläre Methoden zu verwenden, die anstelle von statischen Methoden überschrieben werden können.

Wenn Sie weiterhin statische Methoden verwenden möchten, stellen Sie sicher, dass die Aufrufe Thread-sicher sind, wenn sie in einem Kontext mit mehreren Threads verwendet werden. (z. B. doppelt geprüfte Verriegelung).

  • Statische Methoden != Singleton. Bei Utility-Klassen mit nur statischen Methoden gibt es oft überhaupt keine Instanz der Klasse.

    – Markus

    14. Juli 2015 um 15:00 Uhr

Klassen mit nur statischen Methoden sind in Java ein gängiges Muster für Hilfsmethoden. Beispiele in der Standardbibliothek umfassen Dateien, Sammlungenund Vollstrecker.

Bei solchen Hilfsklassen ist es eine gute Idee sicherzustellen, dass Ihre Klasse nicht instanziiert werden kann, um die Absicht der Klasse klar zu machen. Sie können dies tun, indem Sie explizit einen privaten Konstruktor deklarieren. Sehen Punkt 4: Nicht-Instanzierbarkeit mit einem privaten Konstruktor erzwingen in “Effective Java” von Josh Bloch für Details.

  • Statische Methoden != Singleton. Bei Utility-Klassen mit nur statischen Methoden gibt es oft überhaupt keine Instanz der Klasse.

    – Markus

    14. Juli 2015 um 15:00 Uhr

1381280cookie-checkBest Practice für Java: Klasse mit nur statischen Methoden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy