Angenommen, ich habe eine Klasse, die instanziiert werden soll. Ich habe mehrere private "Hilfs" -Methoden innerhalb der Klasse, die keinen Zugriff auf eines der Klassenmitglieder erfordern, und arbeite ausschließlich mit ihren Argumenten und gebe ein Ergebnis zurück.
public class Example {
private Something member;
public double compute() {
double total = 0;
total += computeOne(member);
total += computeMore(member);
return total;
}
private double computeOne(Something arg) { ... }
private double computeMore(Something arg) {... }
}
Gibt es einen bestimmten Grund angeben computeOne
und computeMore
als statische Methoden - oder einen bestimmten Grund nicht zu tun?
Es ist sicherlich am einfachsten, sie als nicht statisch zu belassen, obwohl sie ohne Probleme statisch sein können.
java
static
methods
static-methods
Lawinen
quelle
quelle
Antworten:
Ich bevorzuge solche Hilfsmethoden
private static
; Dadurch wird dem Leser klar, dass er den Status des Objekts nicht ändert. Meine IDE zeigt auch Aufrufe statischer Methoden in Kursivschrift an, sodass ich weiß, dass die Methode statisch ist, ohne auf die Signatur zu achten.quelle
protected static
diese Hilfsmethoden als solche, die sie in einer Testklasse im selben Paket sehr einfach testbar machen.static
(wenn wir es nur zum Testen wollen).Dies kann zu einem etwas kleineren Bytecode führen, da die statischen Methoden keinen Zugriff erhalten
this
. Ich denke nicht, dass es einen Unterschied in der Geschwindigkeit macht (und wenn es so wäre, wäre es wahrscheinlich zu klein, um insgesamt einen Unterschied zu machen).Ich würde sie statisch machen, da ich dies im Allgemeinen tue, wenn es überhaupt möglich ist. Aber das bin nur ich.
BEARBEITEN: Diese Antwort wird immer wieder abgelehnt, möglicherweise aufgrund der unbegründeten Behauptung über die Bytecode-Größe. Also werde ich tatsächlich einen Test durchführen.
Bytecode (abgerufen mit
javap -c -private TestBytecodeSize
):Das Aufrufen der statischen Methode erfordert zwei Bytecodes (Byteops?):
iconst_0
(Für das Argument) undinvokestatic
.Das Aufrufen der nicht statischen Methode erfordert drei:
aload_1
(für dasTestBytecodeSize
Objekt, nehme ich an),iconst_0
(für das Argument) undinvokespecial
. (Beachten Sie, dass, wenn dies keine privaten Methoden gewesen wären, diesinvokevirtual
stattdessen gewesen wäreinvokespecial
; siehe JLS §7.7 Aufrufen von Methoden .)Nun, wie gesagt, ich erwarte keinen großen Leistungsunterschied zwischen diesen beiden, abgesehen von der Tatsache,
invokestatic
dass ein Bytecode weniger erforderlich ist.invokestatic
undinvokespecial
sollten beide etwas schneller sein alsinvokevirtual
, da beide statische Bindung anstelle von dynamischer verwenden, aber ich habe keine Ahnung, ob einer schneller als der andere ist. Ich kann auch keine guten Referenzen finden. Der nächstgelegene, den ich finden kann, ist dieser JavaWorld-Artikel von 1997 , in dem im Grunde das wiederholt wird, was ich gerade gesagt habe:Aber seit 1997 haben sich viele Dinge geändert.
Also abschließend ... Ich denke, ich bleibe immer noch bei dem, was ich vorher gesagt habe. Geschwindigkeit sollte nicht der Grund sein, sich für eine andere zu entscheiden, da dies bestenfalls eine Mikrooptimierung wäre.
quelle
Meine persönliche Präferenz wäre es, sie für statisch zu erklären, da es eine klare Flagge ist, dass sie zustandslos sind.
quelle
Die Antwort ist ... es kommt darauf an.
Wenn member eine Instanzvariable ist, die für das Objekt, mit dem Sie sich befassen, spezifisch ist, warum sollten Sie sie dann überhaupt als Parameter übergeben?
Zum Beispiel:
quelle
Ein Grund, warum Sie möglicherweise statische Hilfsmethoden deklarieren möchten, besteht darin, dass Sie sie im Klassenkonstruktor "vor"
this
oder "aufrufen" müssensuper
. Beispielsweise:Dies ist ein erfundenes Beispiel,
recoverInt
kann aber in diesem Fall eindeutig keine Instanzmethode sein.quelle
Ich kann mir keine klaren Vorteile für die private statische Methode vorstellen. Abgesehen davon gibt es auch keine besonderen Vorteile, wenn sie nicht statisch sind. Es ist hauptsächlich eine Frage der Präsentation: Vielleicht möchten Sie sie statisch machen, um deutlich zu machen, dass sie ein Objekt nicht verändern.
Für Methoden mit unterschiedlichen Zugriffsrechten gibt es meines Erachtens zwei Hauptargumente:
Abgesehen davon ist der Unterschied ziemlich gering, und ich bezweifle stark, dass das Extra, das dieser Zeiger an die Instanzmethode übergeben hat, einen signifikanten Unterschied macht.
quelle
Die richtige Antwort lautet:
Jede Methode, die keine Informationen aus einem Feld entnimmt und keine Informationen in ein Feld einfügt, muss keine Instanzmethode sein. Jede Methode, die keine Felder in ihrer Klasse oder ihrem Objekt verwendet oder ändert, kann auch eine statische Methode sein.
quelle
Ja.
Indem Sie sie als Instanzmethoden beibehalten, können Sie später eine andere Implementierung bereitstellen.
Es mag albern klingen (und tatsächlich wäre es, wenn diese Methoden nur von Ihnen in einem 50-Zeilen-Programm verwendet werden), aber in größeren Anwendungen oder in Bibliotheken, die von jemand anderem verwendet werden, können Sie sich für eine bessere Implementierung entscheiden, aber nicht möchte vorhandenen Code brechen.
Sie erstellen also eine Unterklasse und geben diese in den neuen Versionen zurück. Da die Methoden als Instanzmethoden deklariert wurden, lassen Sie den Polymorphismus einfach seine Aufgabe erledigen.
Darüber hinaus können Sie davon profitieren, den Konstruktor privat zu machen und aus demselben Grund eine statische Factory-Methode bereitzustellen.
Daher empfehle ich, sie als Instanzmethoden beizubehalten und statische Störungen nach Möglichkeit zu vermeiden.
Nutzen Sie die Dynamik der Sprache.
Hier finden Sie ein etwas verwandtes Video: Wie man eine gute API entwirft und warum es wichtig ist
Obwohl es nicht direkt mit der Diskussion der Methode "statisch gegen Instanz" zusammenhängt, werden einige interessante Punkte im API-Design angesprochen.
quelle
Ein Problem bei statischen Methoden besteht darin, dass die Verwendung des Objekts in Komponententests erschwert werden kann . Mockito kann keine Mocks für statische Methoden erstellen und Sie können keine Unterklassenimplementierung der Methode erstellen.
quelle
Wenn die Methode im Grunde nur eine Unterroutine ist, die niemals vorhersehbar Statusinformationen verwendet, deklarieren Sie sie als statisch.
Dies ermöglicht die Verwendung in anderen statischen Methoden oder bei der Klasseninitialisierung, dh:
quelle
Meine Präferenz in Fällen wie diesen zu machen
computeOne
undcomputeMore
statische Methoden. Der Grund: Kapselung. Je weniger Code Zugriff auf die Implementierung Ihrer Klasse hat, desto besser.In dem Beispiel, das Sie geben, geben Sie an, dass Sie nicht auf die Interna der Klasse zugreifen müssen
computeOne
undcomputeMore
sollten. Warum sollten Sie also den Betreuern der Klasse die Möglichkeit geben, sich in die Interna einzumischen?quelle
Ich möchte einige Dinge klarstellen, die andere Plakate als falsche Informationen bezeichnet haben.
Erstens können Sie außerhalb dieser Klasse nicht auf sie zugreifen, da die Methoden privat sind, auch wenn Sie sie als statisch deklarieren. Zweitens sind sie privat, sodass Sie sie nicht einmal in der Unterklasse überschreiben können, sodass statisch oder nicht statisch keinen Unterschied macht. Drittens kann eine nicht statische private Methode auch von einem Konstruktor der Klasse aufgerufen werden, sie muss nicht statisch sein.
Kommen wir nun zu Ihrer Frage, ob eine private Hilfsmethode als statisch oder nicht statisch definiert werden soll. Ich werde mit Steves Antwort fortfahren, da das Markieren einer statischen privaten Methode zeigt, dass diese Methode zustandslos ist, da ich diese Regel auch beim Codieren befolge.
quelle
Aus der Erfahrung würde ich sagen, dass solche privaten Methoden in der Regel ziemlich universell und wiederverwendbar sind.
Ich denke, das erste, was zu tun ist, ist die Frage zu stellen, ob die Methode außerhalb des aktuellen Klassenkontexts nützlich sein kann. Wenn ja, würde ich genau das tun, was jeder vorschlägt, und diese Methode als statisch für eine Utils-Klasse extrahieren, in der hoffentlich jemand prüft, bevor er eine neue Methode implementiert, die genau dasselbe tut.
Solche allgemein verwendeten privaten Methoden sind die Quelle eines großen Teils der Codeduplizierung im Projekt, da jeder Entwickler sie unabhängig neu erfindet, genau an der Stelle, an der er sie verwenden muss. Die Zentralisierung solcher Methoden ist also ein langer Weg.
quelle
Die statische / nicht statische Frage lautet: "Muss ich wirklich ein Objekt dieser Klasse verwenden?"
Übergeben Sie das Objekt also zwischen verschiedenen Methoden? Enthält das Objekt Informationen, die außerhalb des Kontexts der statischen Methoden nützlich sind? Gibt es einen Grund, Methoden nicht in beide Richtungen zu definieren, wenn Sie sie in beide Richtungen verwenden?
Wenn Sie sich in diesem Dilemma befinden, scheint es mir, dass Sie alle Daten, die für die Methode erforderlich sind, in Ihrem Code außerhalb des Objekts haben. Ist das was du willst? Wäre es einfacher, diese Daten jedes Mal in einem Objekt zu sammeln? Sie sind möglicherweise nur ambivalent, wenn Sie sich auf ein einzelnes Modell festlegen. Wenn Sie alles auf eine Weise erledigen können, wählen Sie entweder statisch oder nicht statisch und fahren Sie fort.
quelle
Insbesondere in dem von Ihnen angegebenen Beispiel scheint der Zweck der Definition dieser Methoden eher der Klarheit des Codes beim Lesen als der Funktionalität zu dienen (sie sind als privat definiert). In diesem Fall bringt die Verwendung von static nichts für Sie, da der Zweck von static darin besteht, die Klassenfunktionalität verfügbar zu machen.
quelle
Ein Grund dafür ist, dass statische Methodenaufrufe bei sonst gleichen Bedingungen schneller sein sollten. Statische Methoden können nicht virtuell sein und implizieren diese Referenz nicht.
quelle
Wie viele Leute sagten, machen Sie es als statisch ! Hier ist die Daumenregel, der ich folge: Wenn Sie denken, dass die Methode nur eine mathematische Funktion ist, dh sie ist zustandslos, enthält sie keine Instanzvariablen (=> keine blauen Farbvariablen [in Eclipse] in der Methode) und das Ergebnis von Die Methode ist für 'n' Anzahl von Aufrufen (natürlich mit denselben Parametern) dieselbe. Markieren Sie diese Methode dann als STATISCH.
Wenn Sie der Meinung sind, dass diese Methode für andere Klassen nützlich ist, verschieben Sie sie andernfalls in eine Util-Klasse. Fügen Sie die Methode als privat in dieselbe Klasse ein. (Minimierung der Zugänglichkeit)
quelle
Off-Topic: Ich würde die Hilfsmethoden in einer eigenständigen Dienstprogramm- / Hilfsklasse mit nur statischen Methoden behalten.
Das Problem mit Hilfsmethoden am Verwendungsort (lesen Sie "gleiche Klasse") besteht darin, dass sich jemand auf der ganzen Linie möglicherweise dafür entscheidet, seine eigenen nicht verwandten Hilfsmethoden an derselben Stelle zu veröffentlichen
quelle
Der Vorteil privater statischer Methoden besteht darin, dass sie später wiederverwendet werden können, wenn Sie die Klassenvariable neu initialisieren müssen.
quelle
Ohne den statischen Modifikator können Sie ohne zusätzliche Analyse nicht herausfinden, dass die Methode zustandslos ist. Dies ist einfach, wenn Sie die Methode (neu) schreiben.
Dann kann der "statische" Modifikator Ihnen neben anderen Dingen, die andere möglicherweise als nutzlos empfinden, Ideen zum Refactoring geben. ZB Verschieben der Methode in eine Utility-Klasse oder Konvertieren in eine Member-Methode.
quelle
Ich würde sie als statisch deklarieren, um sie als zustandslos zu kennzeichnen.
Java hat keinen besseren Mechanismus für kleinere Operationen, die nicht exportiert werden. Daher halte ich private statische Aufladungen für akzeptabel.
quelle