Ist es eine schlechte Praxis für eine Klasse, nur statische Felder und Methoden zu haben?

70

Ich habe eine Klasse, die nur aus statischen Elementvariablen und statischen Methoden besteht. Im Wesentlichen dient es als allgemeine Dienstprogrammklasse.

Ist es eine schlechte Praxis für eine Klasse, nur statische Elementvariablen und statische Methoden zu enthalten?

Stephen Watkins
quelle
28
java.lang.Mathist 100% statische Methoden mit einem privateKonstruktor (kann nicht instanziiert werden).
Asaph
Ich bin mir nicht sicher, ob diese Frage in diesem Forum gestellt wurde. Aber ist es eine schlechte Praxis für eine Klasse, nur statische Felder zu haben? Ich habe viele solcher Klassen gesehen und meiner Meinung nach passen sie nicht in OOP.
Ka3ak
@ ka3ak Klassen, die nur statische Felder haben, werden in einigen Antworten auf diese Frage teilweise angesprochen.
Stephen Watkins

Antworten:

88

Nein, das glaube ich überhaupt nicht. Es ist schlimmer, eine Klasse voller Instanzmethoden zu haben, die nicht wirklich von einer bestimmten Instanz abhängen. Wenn Sie sie statisch machen, erfahren Sie genau, wie sie verwendet werden sollen. Außerdem vermeiden Sie auf diese Weise unnötige Instanziierungen.

EDIT: Nachträglich finde ich es im Allgemeinen schön, die Verwendung von Sprachfunktionen "nur weil" zu vermeiden, oder weil Sie denken, dass dies die "Java-Methode" ist. Ich erinnere mich an meinen ersten Job, bei dem ich eine Klasse voller statischer Dienstprogrammmethoden hatte und einer der leitenden Programmierer mir sagte, dass ich die OO-Leistung von Java nicht vollständig nutzen konnte, indem ich alle meine Methoden "global" machte. Sie war 6 Monate später nicht im Team.

danben
quelle
7
Ha - nicht ganz das, was ich damit
meinen wollte
19

Solange die Klasse keinen internen Status hat und im Wesentlichen eine sogenannte Blattklasse ist (Dienstprogrammklassen fallen in diese Kategorie), ist sie mit anderen Worten unabhängig von anderen Klassen. Es ist in Ordnung.

Die MathKlasse ist ein Paradebeispiel.

Finglas
quelle
Haben Sie einen schönen Link / Artikel zu Blatt- / Dienstprogrammklassen?
Zoran Pavlovic
13

Klingt vernünftig.

Hinweis: Klassen, die dies tun, haben häufig einen privaten Konstruktor ohne Argumente, nur damit der Compiler einen Fehler ausgibt, wenn ein Programmierer versucht, eine Instanz der statischen Klasse zu erstellen.

Jason S.
quelle
4
Ein privater Standardkonstruktor verhindert auch die Unterklassifizierung Ihrer statischen Klasse.
David
1
Gibt es einen Grund, warum Sie eine statische Klasse unterordnen möchten? (Ich kann mir keinen vorstellen ... Ich bin kein Sprachguru)
Jason S
4
Das Verhindern von Unterklassen ist in diesem Fall ein "Profi". Es ist möglich, dass jemand anderes, der an Ihrem Projekt arbeitet, versehentlich versucht, Ihre statische Klasse zu unterordnen (durch Tippfehler oder Missverständnisse). Durch Hinzufügen eines privaten Standardkonstruktors fügen Sie Ihrer Klasse mehr Bedeutung hinzu, indem Sie die Verwendung strenger durchsetzen.
David
1
Wenn die Klasse endgültig ist, wird auch eine Unterklassifizierung verhindert.
HexAndBugs
9

Statische Methoden machen mir keine großen Sorgen (außer zum Testen).

Im Allgemeinen sind statische Elemente ein Problem. Was ist zum Beispiel, wenn Ihre App geclustert ist? Was ist mit der Startzeit - welche Art von Initialisierung findet statt? Weitere Informationen zu diesen und weiteren Themen finden Sie in diesem Artikel von Gilad Bracha.

Michael Ostern
quelle
2
+1 für die Unterscheidung zwischen statischen Funktionen (fein) und statischem Zustand (zweifelhaft)
mikera
3

Es ist völlig vernünftig. Tatsächlich können Sie in C # eine Klasse mit dem statischen Schlüsselwort speziell für diesen Zweck definieren.

Taylor Leese
quelle
3

Lass dich einfach nicht mitreißen. Beachten Sie, dass es in der Klasse java.lang.Math nur um mathematische Funktionen geht. Möglicherweise verfügen Sie auch über eine StringUtilities-Klasse, die allgemeine Funktionen zur Behandlung von Zeichenfolgen enthält, die beispielsweise nicht in der Standard-API enthalten sind. Wenn Ihre Klasse beispielsweise Utilities heißt, ist dies ein Hinweis darauf, dass Sie sie möglicherweise aufteilen möchten.

Paul Clapham
quelle
2

Beachten Sie auch, dass Java speziell den statischen Import eingeführt hat: ( http://en.wikipedia.org/wiki/Static_import )

Der statische Import ist eine in der Java-Programmiersprache eingeführte Funktion, die Mitglieder (Felder und Methoden) in einer Klasse als öffentliche statische Elemente definieren, die im Java-Code verwendet werden sollen, ohne die Klasse anzugeben, in der das Feld definiert ist. Diese Funktion wurde in Version 5.0 in die Sprache eingeführt.

Die Funktion bietet einen typsicheren Mechanismus zum Einfügen von Konstanten in den Code, ohne auf die Klasse verweisen zu müssen, die das Feld ursprünglich definiert hat. Es hilft auch, die Praxis des Erstellens einer konstanten Schnittstelle zu verwerfen: Eine Schnittstelle, die nur Konstanten definiert und dann eine Klasse schreibt, die diese Schnittstelle implementiert, was als unangemessene Verwendung von Schnittstellen angesehen wird [1].

Der Mechanismus kann verwendet werden, um auf einzelne Mitglieder einer Klasse zu verweisen:

 import static java.lang.Math.PI;
 import static java.lang.Math.pow;

oder alle statischen Mitglieder einer Klasse:

 import static java.lang.Math.*;
peter.murray.rust
quelle
Ich denke, das ist ein wenig abseits des Themas für das, was er fragt. Der statische Import hat nichts damit zu tun, ob eine Klasse NUR statische Mitglieder hat. es funktioniert, wenn es welche gibt.
Danben
1
Sowohl gute Informationen als auch ein gutes Argument dafür, warum wir dies tun sollen.
Chuck
Entschuldigung, ich bin anderer Meinung - ich denke, es ist ein Argument für statische Methoden, aber es sagt nichts darüber aus, Klassen zu haben, die nicht dazu gedacht sind, instanziiert zu werden.
Danben
@danben: Statische Importe sind (zumindest für mich) für eine Klasse, die Sie instanziieren möchten, weniger sinnvoll. Dies ist am sinnvollsten bei "Dienstprogrammklassen", die viele statische Methoden wie java.lang.Math enthalten. Glaubst du nicht?
Chuck
Könnte hier nicht picken, aber ich stimme Ihnen zu, wenn Sie sagen, dass sie in einer Klasse, die Sie instanziieren werden, weniger Sinn machen; Ich stimme jedoch nicht zu, dass sie für eine Klasse, die nicht instanziiert werden kann, sinnvoller sind.
Danben
2

Ich stimme zwar dem Gefühl zu, dass es sich nach einer vernünftigen Lösung anhört (wie andere bereits festgestellt haben), aber eine Sache, die Sie in Betracht ziehen sollten, ist aus gestalterischer Sicht, warum Sie eine Klasse nur für "Nutzen" -Zwecke haben. Sind diese Funktionen im gesamten System wirklich allgemein oder beziehen sie sich wirklich auf eine bestimmte Klasse von Objekten in Ihrer Architektur?

Solange Sie darüber nachgedacht haben, sehe ich kein Problem mit Ihrer Lösung.

JasCav
quelle
1

Die Collections- Klasse in Java SDK hat nur statische Mitglieder.

Also los, solange Sie die richtige Rechtfertigung haben - es ist kein schlechtes Design

Mihir Mathuria
quelle
1

Dienstprogrammmethoden werden häufig in Klassen mit nur statischen Methoden (wie z StringUtils. B. ) platziert. Globale Konstanten werden auch in ihrer eigenen Klasse platziert, damit sie vom Rest des Codes ( public final staticAttribute) importiert werden können .

Beide Verwendungen sind weit verbreitet und verfügen über private Standardkonstruktoren, um zu verhindern, dass sie instanziiert werden. Das Deklarieren des Klassenfinales verhindert den Fehler, statische Methoden zu überschreiben.

Wenn static member variablesSie damit nicht globale Konstanten gemeint haben, möchten Sie möglicherweise die Methoden, die auf diese Variablen zugreifen, in eine eigene Klasse einfügen. Könnten Sie in diesem Fall erläutern, was diese Variablen in Ihrem Code bewirken?

rsp
quelle
1

Nach einer starren Interpretation des objektorientierten Designs ist eine Gebrauchsklasse zu vermeiden.

Das Problem ist, dass Sie, wenn Sie einer starren Interpretation folgen, Ihre Klasse in ein Sortierobjekt zwingen müssen, um viele Dinge zu erreichen.

Sogar die Java-Designer erstellen Dienstprogrammklassen (java.lang.Math fällt mir ein)

Ihre Optionen sind:

double distance = Math.sqrt(x*x + y*y);  //using static utility class

vs:

RootCalculator mySquareRooter = new SquareRootCalculator();
mySquareRooter.setValueToRoot(x*x + y*y);
double distance;
try{
   distance = mySquareRooter.getRoot();
}
catch InvalidParameterException ......yadda yadda yadda.      

Selbst wenn wir die ausführliche Methode vermeiden würden, könnten wir dennoch Folgendes erreichen:

Mathemetician myMathD00d = new Mathemetician()
double distance = myMathD00d.sqrt(...);

In diesem Fall ist .sqrt () immer noch statisch. Worum geht es also bei der Erstellung des Objekts überhaupt?

Die Antwort lautet: Erstellen Sie Dienstprogrammklassen, wenn Ihre andere Option darin besteht, eine künstliche "Worker" -Klasse zu erstellen, die beispielsweise keine oder nur geringe Verwendung von Variablen hat.

Chris Cudmore
quelle
1

Dieser Link http://java.dzone.com/articles/why-static-bad-and-how-avoid scheint den meisten Antworten hier zu widersprechen. Selbst wenn es keine Mitgliedsvariablen enthält (dh keinen Status), kann eine statische Klasse immer noch eine schlechte Idee sein, da sie nicht verspottet oder erweitert (unterklassifiziert) werden kann und daher einige der Prinzipien von OO zunichte macht

Andy
quelle
0

Ich würde mir keine Sorgen um eine Utility-Klasse machen, die statische Methoden enthält.

Statische Elemente sind jedoch im Wesentlichen globale Daten und sollten vermieden werden. Sie können akzeptabel sein, wenn sie zum Zwischenspeichern von Ergebnissen der statischen Methoden und dergleichen verwendet werden, aber wenn sie als "echte" Daten verwendet werden, die zu allen Arten von Problemen führen können, wie versteckten Abhängigkeiten und Schwierigkeiten beim Einrichten von Tests.

Sternenblau
quelle