Muss / warum Java void
Methoden haben? Hinweis :
Jede als ungültig deklarierte Methode gibt keinen Wert zurück.
Soweit ich denken kann, ist es für jede Verwendung von void
besser, ein Statusflag zurückzugeben, das Objekt aufzurufen oder null
.
Dies würde jeden Aufruf zu einer zuweisbaren Anweisung machen und die Erstellung von Mustern und die Verkettung von Methoden erleichtern. Methoden, die nur für ihre Auswirkungen aufgerufen werden, geben normalerweise einen Booleschen oder einen generischen Success
Typ zurück oder lösen bei Fehlern eine Ausnahme aus.
java
programming-languages
return-type
marisbest2
quelle
quelle
Antworten:
Denn es gibt einen Unterschied zwischen "Diese Funktion kann erfolgreich sein oder scheitern und ist sich der Tatsache bewusst, dass sie den Unterschied erkennen kann" und "Es gibt kein Feedback zur Auswirkung dieser Funktion." Ohne würden
void
Sie endlos die Erfolgscodes überprüfen und glauben, dass Sie robuste Software schreiben, obwohl Sie nichts dergleichen tun.quelle
void
sagt nichts darüber aus, ob die Methode oder Funktion selbstbewusst genug ist, um entsprechend zu werfen.void
Typ hat und Java so konzipiert wurde, dass es vielen Konventionen der C-Sprachfamilie folgt.Success
Typ" überhaupt machen? Tatsächlich sind Rückgabewerte zur Anzeige des Erfolgs in Java noch weniger wichtig als in C, da Java Ausnahmen zur Anzeige von Fehlern hat und C dies nicht tut.quelle
Void
Typ fungiert als Einheitentyp (z. B. für Generika), unterscheidet sich aber leider vonvoid
(Randnotiz: Ein Kuscheltier stirbt jedes Mal , wenn Sie einen neuen Typ erfinden, um den Typ zu reparieren, den Sie in der vorherigen Version durcheinander gebracht haben). Wenn jemand nicht mit Einheitentypen vertraut ist, ist dies ein anständiges Intro: en.wikipedia.org/wiki/Unit_typenull
(in der Tat ist dies die einzige Wahl), aber null ist eine spezielle Sache, jeder Wert des Referenztyps in Java kann null sein (dies ist ein weiterer Fehler im Sprachdesign). Und wie ich bereits sagte, wenn Sie denVoid
Rückgabetyp anstelle vonvoid
mark verwenden, ist der Java-Compiler nicht Ihr Freund.null
. Die Tatsache, dassnull
es sich um ein Element der meisten Typen handelt, spielt keine Rolle, obVoid
es sich um einen Einheitentyp handelt.Der ursprüngliche Grund, warum die Sprache einen
void
Typ hat, istC
, dass die Ersteller der Sprache die Syntax der Sprache nicht unnötig mit Prozeduren und Funktionen wie Pascal verkomplizieren wollten.Das war der ursprüngliche Grund.
Deine Vorschläge:
Das ist ein Nein-Nein. Wir verwenden keine Statusflags. Wenn etwas schief geht, melden wir es über Ausnahmen.
Der fließende Stil von Anrufungen ist eine neuere Entwicklung. Viele der Programmierer, die heute sehr gerne fließend arbeiten und die Augen verdrehen, wenn sie jemals eine Schnittstelle verwenden müssen, die dies nicht unterstützt, wurden nicht einmal bei der Erstellung von Java geboren.
Das würde Sie zwingen, eine Methode als etwas zurückzugeben, obwohl sie tatsächlich nichts zurückgibt. Es wäre also sehr verwirrend für jemanden, der sich eine Schnittstelle ansieht, um herauszufinden, was sie tut. Die Leute würden unweigerlich eine ansonsten nutzlose Klasse erfinden, die für "kein Rückgabewert" steht, damit alle Funktionen, die nichts zurückzugeben haben, eine Nullreferenz auf eine solche Klasse zurückgeben können. Das wäre klobig. Zum Glück gibt es eine Lösung dafür, heißt es
void
. Und das ist die Antwort auf Ihre Frage.quelle
int
, sodass nach K & R ein Schlüsselwort hinzugefügt wurde, das angibt, dass kein Rückgabetyp vorliegt.Einige Methoden, wie zum Beispiel,
System.out.println
geben nichts Nützliches zurück, sondern werden nur für diesen Nebeneffekt aufgerufen.void
ist ein hilfreicher Indikator für den Compiler und den Codeleser, dass kein nützlicher Wert zurückgegeben wird.Rückgabe
null
stattvoid
bedeutet, dass Sie nurNullPointerException
den Moment erhalten, in dem Sie diesen Wert für alles verwenden. Sie tauschen also einen Fehler bei der Kompilierung gegen einen wesentlich schlechteren Laufzeitfehler. Außerdem müssten Sie den Rückgabetyp als definierenObject
, was irreführend und verwirrend wäre. (Und Verketten würde immer noch nicht funktionieren.)Statuscodes werden normalerweise verwendet, um Fehlerzustände anzuzeigen, aber Java hat Ausnahmen für diesen Zweck.
Rückgabe
this
von statischen Methoden ist nicht möglich.Das Zurückgeben eines generischen
Success
Objekts hätte keinen nützlichen Zweck.quelle
Ein Grund dafür ist , dass es sein kann irreführend jemals etwas zurück andere als beispielsweise
null
. Beispiel:Was soll
Arrays.sort(a)
zurückkehren?Wenn Sie der Meinung sind, dass
a
die Rückgabe erfolgen soll, damit der Anruf verkettet werden kann (was Ihrer Frage nach Ihre Antwort zu sein scheint), ist nicht mehr klar, ob der Rückgabewert eine Kopie des Originalobjekts oder des Originalobjekts selbst ist . Beides ist möglich. Und ja, Sie könnten es in die Dokumentation aufnehmen, aber es ist hinreichend vieldeutig, dass Sie die Mehrdeutigkeit nicht erst erzeugen sollten.Wenn Sie dagegen argumentieren, dass zurückgegeben
null
werden soll, stellt sich die Frage, welche Informationen der Rückgabewert möglicherweise dem Aufrufer bereitstellt und warum der Programmierer zum Schreiben gezwungen werden sollte,return null
wenn er keine Informationen übermittelt.Und wenn Sie etwas völlig Absurdes (wie die Länge von
a
) zurückgeben, ist die Verwendung dieses Rückgabewerts nur verwirrend - denken Sie nur daran, wie verwirrend es ist,int len = Arrays.sort(a)
statt zu sagenint len = A.length
!quelle
return null;
- die JVM könnte genauso gut vorschreiben, dass, wenn die Steuerung durch eine andere Methode als eine explizitereturn
oderthrow
Anweisung vom Ende einer Funktion abweicht, diesnull
implizit an den Aufrufer zurückgegeben wird. IIRC C führt dies aus, mit der Ausnahme, dass der Rückgabewert in diesem Fall undefiniert ist (dies ist der Wert, der sich zufällig an der Stelle befindet, an der sich der Rückgabewert zu diesem Zeitpunkt befindet).return
Aussage vergessen . Stattdessen wird ein Compilerfehler angezeigt, der Sie über Ihren Fehler informiert. Ein Implizit einzufügenreturn null;
wäre besser als "undefiniertes Verhalten", aber nicht viel. Das wäre nur dann sinnvoll, wenn der Rückgabetyp keine Bedeutung hat, aber woher zieht der Compiler die Schlussfolgerung, dass der Rückgabewert keine Bedeutung hat, wenn er keine Bedeutung hatvoid
?return
wirklich keinen Wert hinzufügt ..." Nun, wie gesagt, es gibt keinen Indikator für den Compiler, dass eine Rückgabe keinen Wert hinzufügt, wenn es keinenvoid
Typ gibt. Es ist eigentlich das Gegenteil, die erste Annahme ist, dass eine Methode, die einen Rückgabetyp deklariert,return
etwas Nützliches von diesem Typ haben möchte . Und wir haben noch nicht über primitive Typen gesprochen, die keinennull
Wert haben. Daher würde jeder vom Compiler eingefügte Standardwert mit dem Bereich potenziell nützlicher Rückgabewerte in Konflikt stehen.Das Zurückgeben eines,
boolean
das immer gleich dem ist,true
was Sie vorschlagen, ist nicht nur sinnlos (der Rückgabewert enthält keine Informationen), sondern wäre tatsächlich irreführend. Die meiste Zeit ist es am besten, Rückgabetypen zu verwenden, die nur so viele Informationen enthalten, wie tatsächlich verfügbar sind - deshalb haben Sie in Java 4 Milliarden mögliche Werteboolean
fürtrue
/false
anstatt zurückzugebenint
. Ebensoboolean
wäre es irreführend , ein mit zwei möglichen Werten zurückzugeben, wenn es nur einen möglichen Wert gibt ("generischer Erfolg").Es würde auch unnötigen Leistungsaufwand hinzufügen.
Wenn eine Methode nur für ihre Nebenwirkung verwendet wird, gibt es nichts zurückzugeben, und der Rückgabetyp gibt
void
genau das wieder. Potenzielle seltene Fehler können über Ausnahmen gemeldet werden.Eine Sache, die verbessert werden könnte, wäre die Herstellung
void
eines tatsächlichen Typs wie ScalaUnit
. Dies würde einige Probleme wie den Umgang mit Generika lösen.quelle
List.add
Kommt immer wiedertrue
, aber das ist aus Gründen der Vereinbarkeit mit dem weiter gefassten Vertrag vonCollection.add
, alsoSet.add
darftrue
oder wiederkommenfalse
.Java ist eine relativ alte Sprache. Und 1995 (als es erstellt wurde) und kurz danach waren die Programmierer sehr besorgt darüber, wie lange ein Prozess die Kontrolle über den Prozessor und den Speicherverbrauch übernahm. Das Zurückgeben von void würde einige Taktzyklen und ein wenig Speicherverbrauch durch einen Funktionsaufruf eliminieren, da Sie den Rückgabewert nicht auf den Stapel legen müssten und ihn anschließend nicht entfernen müssten.
Effizienter Code gibt Ihnen nichts zurück, was Sie niemals verwenden würden. Daher ist es eine viel bessere Vorgehensweise, wenn Sie eine Leerstelle in etwas einfügen, das einen bedeutungslosen Rückgabewert hat, als einen Erfolgswert zurückzugeben.
quelle
Ich habe Argumente gelesen, die nahelegen, dass die zweite Option (Return
this
) der Ansatz sein solltevoid
. Dies ist eine ziemlich gute Idee, aber der Builder-Ansatz war zum Zeitpunkt der Erstellung von Java nicht sehr beliebt. Wenn es damals so populär war wie heute, könnte dies der Ansatz gewesen sein. Rückkehrnull
ist eine wirklich schlechte Idee, IMO. Ich wünschte, ich wäre überhauptnull
nicht einmal in der Sprache.Das Problem ist nun, dass, wenn eine Methode eine Instanz ihres eigenen Typs zurückgibt, nicht klar ist, ob es sich um ein neues Objekt oder um dasselbe handelt. Oft spielt es keine Rolle (oder sollte es nicht sein), aber manchmal spielt es eine Rolle. Ich nehme an, die Sprache könnte geändert werden, um implizit
this
auf leere Methoden zurückzukommen. Das einzige Problem, an das ich im Moment denken kann, ist, dass es keine Kompilierungswarnungen geben würde, wenn die Methode später geändert würde, um ein neues Objekt desselben Typs zurückzugeben, aber das ist vielleicht keine große Sache. Das aktuelle Typsystem kümmert sich jetzt nicht um diese Art von Änderungen. Wie dies mit der Vererbung / den Schnittstellen zusammenwirkt, wäre zu überlegen, würde es jedoch ermöglichen, alte APIs ohne Builder-Stil so aufzurufen, als ob dies der Fall wäre.quelle
null
nicht Teil der Sprache wäre, würden die Leute alle Arten von Sentinel-Werten verwenden, die bedeuten "Bitte ignorieren Sie dieses Argument / diesen Rückgabewert, es enthält keinen sinnvollen Wert". Das Problem dabeinull
ist nicht das Ding selbst, sondern nur, dass es dazu neigt, falsch benutzt zu werden. Ich würde wetten , dass dieses Problem nur übertrieben sein würde , wenn die standardisiertenull
mit einer Vielzahl von kundenspezifischen Lösungen ersetzt werden würde, wobei jede Implementierung anders verhalten würde wie Nutzung leise ignorieren, oder werfen besondere Ausnahmen anstelle eines standart Null - Zeiger Ausnahme, usw.null
einen geeigneten optionalen Typ (wieMaybe
in Haskell). Das Problem mit Nullen in Java ist, dass es keinen vernünftigen Weg gibt, sofort zu entscheiden, ob ein Wert in der Praxis nullbar ist oder nicht. Dies führt sowohl zu: unnötig defensiver Programmierung (Überprüfung auf Nullen, wo dies sinnlos ist, wodurch der Prozentsatz des Poops im Code erhöht wird) als auch zu versehentlichen NPEs in der Produktion (wenn vergessen wird, zu überprüfen, wo es benötigt wird). Ja, es wird teilweise durch Anmerkungen gelöst, aber sie sind optional, nicht immer aktiviert usw. Sie werden also nicht an Grenzen mit Code von Drittanbietern gerettet.null
Funktioniert hierfür gut (fine = simple), aber standardisierte optionale Werte mit fester Semantik sind definitiv eine weitere gute Option (fine = safe).Ein anderer Aspekt:
Java ist eine statische Sprache mit sehr strengen Merkmalen. Dies bedeutet, dass viele Dinge, die in anderen Sprachen ziemlich offen oder dynamisch wären (c / f Ruby, Lisp usw.), streng bestimmt sind.
Dies ist eine allgemeine Entwurfsentscheidung. Das "Warum" ist schwer zu beantworten (gut, weil die Designer der Sprache dachten, es wäre gut!). Das "Wofür" ist ziemlich klar: Es lässt den Compiler viele Fehler erkennen, was im Allgemeinen für jede Sprache ein ziemlich gutes Feature ist. Zweitens ist es vergleichsweise einfach, über die Sprache nachzudenken. Beispielsweise ist es relativ einfach, formale Korrektheit zu erstellen, die sich in (Teilmengen von) der Java-Sprache nachweist. Zum Vergleich: In einer dynamischen Sprache wie Ruby et al.
Dieses Denken durchdringt die Sprache, zum Beispiel die erzwungene Deklaration möglicher Ausnahmen, die eine Methode auslösen kann, die getrennte Art von
interface
vs.class
, um mehrdeutige Mehrfachvererbung zu vermeiden, und so weiter. Für das, was es ist (eine statische, zwingende OOP-Sprache in der realen Welt mit starkem Fokus auf der Fehlerbehandlung zur Kompilierungszeit), sind diese Dinge tatsächlich recht elegant und mächtig. Sie kommen theoretischen (naturwissenschaftlichen) Sprachen näher, die gezielt entwickelt wurden, um einige dieser Themen zu untersuchen, als jede andere reale Sprache zuvor (zu diesem Zeitpunkt wohlgemerkt).Damit. Ein strikter
void
Typ ist eine eindeutige Meldung: Diese Methode gibt nichts zurück, Punkt. Es ist was es ist. Das Ersetzen durch die Erzwingung, immer etwas zurückzugeben, würde entweder zu einem viel dynamischeren Verhalten führen (wie in Ruby, wo jedes Def immer einen expliziten oder impliziten Rückgabewert hat), was für die Beweisbarkeit und Argumentation schlecht wäre; oder zu massiv aufblähen, indem Sie hier einen anderen Mechanismus verwenden.(Und NB, Ruby (zum Beispiel) handhabt dies anders und seine Lösung ist immer noch genauso akzeptabel wie die von Java, da es eine völlig andere Philosophie hat. Zum Beispiel wirft es Beweisbarkeit und Vernünftigkeit komplett aus dem Fenster, während es einen großen Fokus darauf legt extrem hohe Ausdruckskraft der Sprache.)
quelle