Ist es in Java immer eine schlechte Idee, die Mitglieder eines Objekts öffentlich zugänglich zu machen?

7

Ich habe eine Datenklasse in meiner Anwendung. Meine Anwendung wird niemals als öffentliche API verwendet und ich bin die einzige Person, die Code in meinem Projekt entwickelt.

Ich versuche, jede Menge Prozessor- und Speicherleistung zu sparen, die ich kann.

Ist es eine schlechte Idee, meinen Datenmitgliedern in meiner Datenklasse den Status public / protected / default zu geben, damit ich keinen Getter verwenden muss? Die Verwendung eines Getters würde etwas mehr Speicher und die Erstellung eines Stacks erfordern und so ... was ich nicht für notwendig halte. Der einzige Grund, den ich bei der Verwendung eines Getters sehen kann, ist Schutz / Privatsphäre. Aber wenn ich der einzige Programmierer bin und niemand sonst meine API benutzt, ist es dann eine schlechte Idee, die Getter nicht zu benutzen?

>

Bitte lassen Sie mich wissen, wenn das dumm ist.

    
jbu 16.02.2009, 22:06
quelle

28 Antworten

24

Wenn Sie Getter / Setter für Performance- / Speicheroptimierung ersetzen, gehen Sie die falsche Methode ein. Dies wird mit ziemlicher Sicherheit nicht der Grund sein, warum Ihre Anwendung langsam läuft oder zu viel Speicher verbraucht.

Die Hauptsünde der Optimierung ist es, es zu tun, bevor Sie wissen, dass Sie es müssen. Optimieren Sie nur, wenn Sie über echte Informationen verfügen, die Ihnen zeigen, wo am meisten Zeit / Speicher verloren geht, und verbringen Sie dann Ihre Zeit damit, diese zu optimieren. Der Gedanke dahinter ist, dass Sie mehr gewinnen, wenn Sie in einem Code, der 80% der Laufzeit in Anspruch nimmt, 5% Zeit einsparen und dann sogar 20% in einem Code, der nur 5% dazu beiträgt die gesamte Laufzeit. (Gleiches gilt für Speicher).

Ich würde auch beim Entwurf der Anwendung vorsichtig sein, wie Sie es vorschlagen, da dies bedeutet, dass einige Eigenschaften (zB: einfache Eigenschaften) direkt zugänglich sind, während andere (komplexere abgeleitete Eigenschaften oder Eigenschaften, die Sie nicht wollen) um die zugrunde liegenden Typen verfügbar zu machen) haben Getter / Setter. Sie erhalten also eine Mischung aus Zugriffsarten, die weniger wartbar sind.

    
KarstenF 16.02.2009 22:21
quelle
11

Es ist eine schlechte Idee , Mitglieder als Optimierung öffentlich zugänglich zu machen . Wie andere gesagt haben, wird es praktisch keine Auswirkungen haben. Wenn das Objekt jedoch eine einfache Datenstruktur mit wenig Verhalten ist, ist es in Ordnung , es so zu schreiben. Solange Sie es tun für Einfachheit und Lesbarkeit , nicht Leistung.

    
Craig P. Motlin 16.02.2009 22:23
quelle
8

Die Chancen stehen gut, dass triviale Getter und Setter sowieso inline sind - aber bei öffentlichen Feldern haben Sie die Unterscheidung zwischen Contract (API) und Implementierung verloren. Selbst wenn dies nur eine API ist, die Sie verwenden wird, ist es gut, die Dinge locker mit IMO gekoppelt zu halten.

    
Jon Skeet 16.02.2009 22:15
quelle
4

Python Leute benutzen keine Getter und sie brennen nicht in der Hölle.

Getter / Setter ist eine Möglichkeit, einen Teil der Klasse der einfachen Introspektion von Java auszusetzen. Die Java Bean-Spezifikation beruht auf öffentlichen Gettern und Settern, um zu bestimmen, welche Attribute wichtig sind.

Obwohl es für Dinge wichtig ist, die Bohnen erfordern / produzieren / verwenden, ist es kein wesentliches Merkmal der OO-Programmierung oder der Java-Programmierung. Es ist nur ein Teil der Bean-Spezifikation und wird für jede Klasse benötigt, die an Bean-ähnlichen Dingen teilnehmen möchte.

Öffentliche Attribute sind in Ordnung. Sie sind einfach, direkt und offensichtlich.

    
S.Lott 16.02.2009 22:15
quelle
4

Wie bei jeder Optimierung, messen Sie vorher und nachher, um zu sehen, ob es einen Nutzen gibt, der die Nachteile rechtfertigt.

Ich denke, dass Sie feststellen werden, dass es keinen merklichen Unterschied zur Leistung Ihres Codes macht (aber versuchen Sie es selbst). Die JVM wird häufig verwendete Getter und Setter inline.

Verwenden Sie einen Profiler und finden Sie die echten Hotspots in Ihrer Anwendung. Optimierung ohne Beweise ist nur Vermutung.

    
Dan Dyer 16.02.2009 22:22
quelle
3

Das ist ein wenig ketzerisch, aber ich stimme Ihnen zu, dass wenn Sie wissen, dass niemand anderes Ihre Klasse benutzen wird, Sie dieses Zeug überspringen können. Ich würde es nicht in Code tun, der wiederverwendet werden könnte, selbst wenn er hinter einer API versteckt ist, aber in Ihrem Fall scheint er ziemlich sicher zu sein.

    
Paul Tomblin 16.02.2009 22:11
quelle
2

Ich bin mir ziemlich sicher, dass die Menge an Speicher vernachlässigbar ist. Die JVM könnte sogar die Aufrufe optimieren, um sie abhängig von der Implementierung zur Laufzeit inline zu machen, wenn Sie für die Produktion erstellen. Wenn Sie es selbst entwickeln, kann es immer noch hilfreich sein, denn wenn Sie einen schwer zu verfolgenden Fehler haben, können Sie einen Haltepunkt im Getter / Setter setzen und genau sehen, wann Sie die Werte ändern. Es sollte auch kein Code zum Schreiben sein, da die meisten modernen IDEs Funktionen haben, um den Code automatisch zu erzeugen.

    
GBa 16.02.2009 22:13
quelle
2

Alle vorzeitigen Optimierungsprobleme wurden in den vorherigen Antworten besprochen.

Ich dachte nur, es ist erwähnenswert, dass Sie in Java die Strukturen von C imitieren können, indem Sie eine Klasse mit nur öffentlichen Elementen wie folgt definieren:

%Vor%

und auf die nur durch Bezugnahme auf diese öffentlichen Mitglieder zugegriffen wird (Holen und Setzen).

Dieses Idiom ist in bestimmten Szenarien völlig akzeptabel.

    
Yuval Adam 16.02.2009 22:40
quelle
2

Getters und Setter sind nicht nur für Schutz / Privatsphäre. Die Hauptverwendung besteht darin, die Art und Weise zu ändern, in der Sie die zugrunde liegenden Daten verfügbar machen.

Zum Beispiel kann in asp.net c # die sichtbare Eigenschaft eines Steuerelements etwas haben wie:

%Vor%

Die externe Eigenschaft (Accessor / Mutator) hat eine andere Bedeutung als die zugrunde liegende Variable. Wenn Sie beim Start nicht über die oben genannten Funktionen verfügen, können Sie bei einfachen gets / sets leicht zu einem späteren Zeitpunkt etwas hinzufügen.

Was den Leistungspunkt betrifft und Sie können jede Unze Prozessor und Speicher sparen. Wenn das einen spürbaren Einfluss hat, dann ist es wahrscheinlich besser, eine andere Sprache zu sehen.

    
Robin Day 16.02.2009 22:45
quelle
2

Ich habe mir nie gewünscht, dass ich ein öffentliches Feld anstelle einer Eigenschaft hätte, aber ich kann nicht zählen, wie oft ich eine Immobilie wollte und ein öffentliches Feld hatte. Irgendwann am Ende willst du Logik drin haben.

    
MNGwinn 16.02.2009 23:04
quelle
2

Ich denke, die Umkehrung dieser Frage ist eine bessere Frage:

Ist es immer eine gute Idee, ein Objekt für Mitglieder öffentlich zugänglich zu machen?

Bei der Entwicklung ist es im Allgemeinen eine gute Idee, die Dinge aus dem Grundsatz zu betrachten, die niedrigste Zugänglichkeitsstufe zu verwenden; Mit anderen Worten: Geben Sie nur so viele Daten frei, wie Sie benötigen. Wenn Sie dieses Prinzip allgemein anwenden, wird es eher eine Praxis, nur soviel zu teilen, wie benötigt wird.

Also mit dem gesagt - warum das?

    
matt b 17.02.2009 00:19
quelle
2

Bedenken Sie, dass sobald Sie etwas in eine öffentliche API einfügen, diese in Stein gemeißelt ist. Sie können den Namen nicht ändern, Sie können den Typ nicht ändern, Sie können nicht ändern, wie er gespeichert wird.

Wenn man es hinter eine Methode stellt, ergibt sich keine Leistung auf einer modernen VM (so ziemlich alles in den letzten 10 Jahren).

Die Flexibilität, die Sie aus Methoden haben, um den Wert zu erhalten, ist meiner Meinung nach wichtiger.

Wenn Sie sich entschließen, sie öffentlich zu machen, stellen Sie sicher, dass Sie sie als endgültig markieren und dass sie unveränderlich sind.

%Vor%

Bearbeiten:

Mit der öffentlichen API meine ich eine beliebige Variable, die öffentlich ist, und nicht, dass die Klasse selbst für andere Entwickler Teil der bereitgestellten API wäre. Wenn Sie es öffentlich machen, können Sie sich später selbst Probleme machen (wenn es sich um eine "echte" öffentliche API handelte, auf die andere Entwickler Zugriff hatten, ist sie buchstäblich in Stein gemeißelt, außer Sie brechen Code anderer Leute, wenn Sie ein Update veröffentlichen).

>     
TofuBeer 16.02.2009 22:24
quelle
1

Es ist nicht dumm, aber ich denke, es ist wahrscheinlich auch keine gute Idee.

Ich verstehe die Versuchung ... wenn niemand sonst den Code benutzt, dann brauchst du dir darüber keine Sorgen zu machen. Aber immer wieder stellt sich heraus, dass dies einfach nicht mit dem übereinstimmt, was tatsächlich passiert ... Sie finden heraus, dass Sie es an mehr Orten verwenden, als Sie dachten, oder das Projekt wird größer als erwartet, oder nur jemand bekommt es in Erinnerung und hält es für nützlich ... Dinge, die niemals dauerhaft oder öffentlich sein sollten, können so werden.

Gibt es wirklich eine Grenze für Prozessorleistung und Speicher? Ich weiß nichts über Ihre Situation (eingebettete App, vielleicht?), Aber als eine (übergeneralisierte) Regel suchen Sie besser woanders nach Ressourcen ... in Ihren Datenstrukturen, Algorithmen oder Archetkturen, um bessere Verbesserungen zu sehen Speicher oder CPU.

    
Beska 16.02.2009 22:13
quelle
1

Sie wissen nie, immer Code, als ob die Leute, die Ihren Code lesen, wissen, wo Sie leben und Serienmörder sind. Selbst wenn Sie Code nur für sich selbst entwickeln, versuchen Sie es (imo) so zu tun, als würden Sie sich in einem Team entwickeln. Auf diese Weise gewöhnen Sie sich daran, lesbaren Best-Practice-Code zu erstellen. Im Hinblick auf den Leistungs-Overhead ist es vielleicht besser, es in etwas wie C zu tun, wenn Sie wirklich wirklich jedes Bit Ihres Speichers und jeden Zyklus Ihrer CPU wirklich brauchen.

    
TomHastjarjanto 16.02.2009 22:16
quelle
1

IMHO, für Eigenschaften, die von Natur aus nur dazu gedacht sind, Daten passiv zu halten und nichts komplizierter zu machen, ohne ihre Bedeutung aus der Sicht des API-Benutzers zu verändern, sind Getter und Setter nur unnötige Standardwerte. Wenn die Eigenschaft ist und von Natur aus eindeutig immer sein wird, nur ein Dateninhaber, wie eine Klasse, die ähnlich wie eine C-Struktur verwendet wird, nur die dumme Sache öffentlich machen. Als allgemeinere Aussage können Best Practices leicht zu Zeitverschwendung oder sogar zu den schlimmsten Praktiken werden, wenn sie übertrieben angewendet werden, ohne darüber nachzudenken, warum sie zu den besten Praktiken gehören. Heck, sogar Goto ist wohl hin und wieder gerechtfertigt.

    
dsimcha 16.02.2009 22:28
quelle
1

Mögliche Nachteile für die Verwendung

  

public final Geben Sie var ;

ein

statt

  

private final Geben Sie var ;

ein      

public Geben Sie get var () {return var ;}

ein

(was ich persönlich erlebt habe) beinhalten:

  • Die Aussicht - wie unwahrscheinlich es jetzt auch scheint - dass die Repräsentation sich ändern muss, in der Basisklasse oder in einer zukünftigen Unterklasse.

  • Die potentielle Unbeholfenheit des Mischens von exponierten, unveränderlich und veränderlich typisierten Feldern.

  • Die Erinnerung daran, welche Klassen public final verwenden und welche get var verwenden.

  • Die Mühe, diese Inkonsistenz jemandem zu erklären, der später den Quellcode sieht.

Ich konnte mich einfach nie davon überzeugen, dass es das wert ist, obwohl ich es versucht habe.

    
joel.neely 16.02.2009 22:52
quelle
1

Ich habe zwei kleine Klassen erstellt und teste sie.

  • Zuerst habe ich ein einzelnes Objekt als Prototyp erstellt.

  • Dann habe ich ein 2.000.000 Array erstellt, um alle zu speichern.

  • Dann habe ich eine Schleife ausgeführt, dort eine neue Instanz erstellt und die Werte aus dem Prototyp übernommen.

Die durchschnittlichen Ergebnisse in Sekunden, in denen jeder einzelne verglichen wird, sind:

%Vor%

Für diesen Fall wäre es also viel besser, eine nicht optimierte Lösung zuerst zu haben, und wenn keine weiteren Anforderungen mehr bestehen, fahren Sie mit der Profilerstellung fort.

Hier ist der Code:

%Vor%     
OscarRyz 16.02.2009 23:20
quelle
1

Wenn Ihre Priorität die Leistung ist, sollten Sie sich die Auswahl der Java Virtual Machine und die Ausführung von Programmen ansehen. Der Desktop Java von Sun verbringt viel Zeit beim Profilieren und Kompilieren von Java-Byte-Code zu Maschinencode, was zu Programmen führt, die sehr schnell laufen können, aber viel Speicher benötigen.

Wenn Sie feststellen, dass Sie eine HotSpot-basierte JVM verwenden möchten, sollten Sie sich alle Tricks ansehen, die Ihnen dabei helfen. Getter und Setter werden normalerweise inline (d. H. Werden anstelle eines Aufrufs einer Subroutine direkt im Maschinencode ersetzt) ​​und Konstanten werden gefaltet. Schalteranweisungen für kleine Bereiche werden normalerweise in eine Sprungtabelle umgewandelt.

Normalerweise finde ich, dass die "Kopf unter dem Arm" -Methode gut funktioniert, um den Großteil des Codes zu schreiben, und dann profiliere ich den laufenden Code und finde die Engpässe. Ich fand zum Beispiel, dass StringBuffers für viele Dinge schnell sind, aber deleteCharAt (0) ist nicht einer von ihnen. Das Umschreiben, um eine einfache Iteration über die Zeichenfolge zu verwenden, anstatt im Zeichenfolgenpuffer zu löschen, hat Wunder bewirkt. Auch Sie werden wahrscheinlich feststellen, dass die größten Vorteile in Algorithmen liegen - keine kleinen Abkürzungen.

In der C-Welt kann der Mensch den Compiler kaum mehr austricksen. In der Java-Welt kann der Mensch HotSpot helfen, indem er direkt Java schreibt.

    
quelle
0

Jede Stapelbenutzung wird sehr vorübergehend sein und keine Gewissheit. Sie können feststellen, dass der Compiler sowieso unnötigen Overhead optimiert, so dass Sie möglicherweise nichts real finden.

Ich stimme zu, dass es nicht unbedingt schlecht für eine private Nicht-API-Klasse ist, öffentliche Mitglieder zu benutzen, aber was du gewinnst, ist so klein (wenn überhaupt), würde ich mich nicht kümmern.

    
cletus 16.02.2009 22:16
quelle
0

Aus der Perspektive, wer den Code geschrieben hat und wer ihn benutzen wird, ist es egal, ob Sie oder jemand anders, Sie brauchen vielleicht noch Getter und Setter - wenn überhaupt jemand sie später benutzt eine defacto public API.

Wenn es jedoch wirklich nur Daten sind und Sie kein mit der Klasse verbundenes Verhalten benötigen, dann sollten Sie die Mitglieder auf jeden Fall öffentlich machen.

Für mich ist es die Frage, ob die Klasse ein Verhalten hat oder ob Sie die Namen oder Typen ihrer Datenmitglieder als wirklich wichtige Details der Implementierung ändern möchten.

Was Prozessorleistung und Speicher betrifft - haben Sie gemessen?

    
quamrana 16.02.2009 22:17
quelle
0

Wenn Geschwindigkeit so wichtig ist, lohnt es sich, sie in C oder C ++ zu schreiben.

    
Jack BeNimble 16.02.2009 23:01
quelle
0

Entwerfen Sie funktional, das Sie nie brauchen werden (Getter / Setter) ist genauso schlecht wie vorzeitige Optimierung. Wenn das wirklich nur für Sie ist, machen Sie es nicht öffentlich und strukturieren Sie es dann, was Sie für das Einfachste halten.

Optimierungen und / oder Getter sollten nur hinzugefügt werden, wenn Sie sie wirklich brauchen.

    
Peter Lawrey 17.02.2009 07:15
quelle
0

Brauchst du den Getter überhaupt ? Das heißt, sollte Ihr Objekt für Sie arbeiten, anstatt dass Ihr Kunde Datenwerte erhält und selbst arbeitet?

Ein wichtiger Aspekt von OOP ist, einem Objekt zu sagen, etwas zu tun, anstatt die Bits herauszuziehen und es selbst zu tun. z. B.

%Vor%

gegen

%Vor%

was ich viel sehe. Oft brauchen Sie Getter (und Setter, vielleicht), aber wenn ich einen Getter schreibe, frage ich mich immer, ob diese Daten offen gelegt werden sollen, oder ob das Objekt sie für mich komplett verbergen soll.

    
Brian Agnew 17.02.2009 12:50
quelle
0

Es ist immer eine schlechte Idee, nicht endgültige Felder öffentlich zu machen.

Was ist, wenn Sie später Ereignisbenachrichtigungen hinzufügen möchten?

Was, wenn Sie das Verhalten später unterklassifizieren und ändern möchten?

Was ist, wenn es einige feldübergreifende Einschränkungen gibt, die Sie erzwingen möchten?

TofuBeer zeigt eine Point-Klasse mit Endfeldern - das ist in Ordnung. Die Point-Klasse in AWT verwendet jedoch keine Finale und hat mich in Java schon früh sehr traurig gemacht.

Ich habe etwas 3D-Code geschrieben und wollte Point so ableiten, dass immer wenn x & amp; y geändert ich könnte z automatisch nach Bedarf anpassen. Da die Felder von Point öffentlich waren, gab es keine Möglichkeit zu wissen, wann x oder y geändert wurde!

    
Scott Stanchfield 17.02.2009 13:13
quelle
0

In unserem Team verwenden wir die folgende Regel: Wenn der durch ein Klassenfeld repräsentierte Zustand veränderbar ist, dann mache ihn immer privat und stelle Mutatoren bereit; Wenn es jedoch unveränderlich ist (d. h. nach der Klasseninstanziierung nicht neu zugewiesen wird), kann es als public final [type] [field-name] - sicher für den Zugriff deklariert werden.

Bitte beachten Sie, dass hier "unveränderlicher Zustand" bedeutet, dass das Feld als final deklariert ist. Sollte nicht mit public [immutable-type] [field-name] verwechselt werden, wo man eine Neuzuweisung durchführen könnte, obwohl die Instanz des unveränderlichen Typs selbst unveränderlich ist.

Bitte beachten Sie auch, dass es viele gute Gründe gibt, Zugriff auf ein unveränderliches Feld zu haben. Zum Beispiel in Fällen, in denen es erforderlich ist, eine Aktion (z. B. Sicherheitsprüfung) zu dem Zeitpunkt durchzuführen, zu dem das Feld gelesen wird.

    
01es 20.02.2009 18:46
quelle
0

Das Argument, dass dieser Code nur für Ihren eigenen Gebrauch gedacht ist, ist eine tote easy-Falle, in die Sie fallen können - das ist der Fall bei den meisten Codes, die öffentlich zugänglichen Bits sind normalerweise sehr klein. Unter der Annahme, dass der meiste Code für den privaten Gebrauch gedacht ist, warum sollte man jemals private, geschützte, finale, const (C / C ++) - retoriale Fragen verwenden, die ich kenne, aber ich hoffe, der Punkt ist klar.

Die andere Sache, die hier verpasst wird, ist das Sperren. Wenn Sie direkt auf das Mitglied zugreifen, können Sie diesen Code nur für das gesamte Objekt oder die Mitgliederebene sperren. Und dieses Sperren wird die Kontrolle über den verwendeten Code haben, nicht das Objekt selbst. Vielleicht in Ordnung, vielleicht nicht, denn in allen Dingen ist es Pferde für Kurse.

    
Tim B 22.02.2009 02:43
quelle
0

Wenn die Leistung von entscheidender Bedeutung ist, würde ich vorschlagen, Felder entweder privat zu machen, wenn sie nur in der gleichen Klasse oder im lokalen Paket verfügbar sind, wenn auf sie in einer anderen Klasse zugegriffen wird. Wenn Sie eine innere / verschachtelte Klasse mit privaten Feldern angeben, fügt der Compiler Zugriffsmethoden hinzu (da die VM Klassen nicht erlaubt, auf Felder in einer anderen Klasse zuzugreifen, obwohl Java dies tut)

Öffentlich veränderbare Felder lassen auf ein Designproblem schließen. Wenn Sie einen leistungskritischen Code verwenden, der auf mehrere Pakete aufgeteilt ist, wird nicht die Art der engen Kodierung vorgeschlagen, die Sie für leistungskritischen Code benötigen.

Wenn Sie unveränderbare Felder haben, habe ich kein Problem, das Feld öffentlich zu machen, vorausgesetzt, Sie erwarten höhere Entwicklungskosten, wenn die Felder das Verhalten ändern. In der Tat schlage ich vor, öffentliche unveränderliche Felder zu verwenden, wenn Sie glauben, dass dies den Code einfacher / leichter verständlich macht.

Die erste Priorität sollte jedoch weiterhin die Lesbarkeit des Codes sein. Der einfachste Code funktioniert oft auch am besten.

    
Peter Lawrey 22.02.2009 03:20
quelle
0

Im Allgemeinen: Wenn Sie etwas manuell optimieren möchten, sollten Sie eher architektonische Verbesserungen als solche Mikrooptimierungen in Erwägung ziehen. Mikrooptimierungen können in vielen Fällen automatisch von einem Werkzeug durchgeführt werden.

Für Java: Es gibt ein ProGuard-Tool, das viele Optimierungen durchführen kann. Wenn Sie jedoch eine moderne JVM (z. B. HotSpot oder OpenJDK) verwenden, kann die JVM diese Optimierungen Just-In-Time durchführen. Wenn Sie eine lange laufende Anwendung haben, wird ProGuard wahrscheinlich eine geringe Auswirkung auf die Leistung haben.

    
v6ak 26.03.2011 11:20
quelle