Warum gibt es in Java keine Konstantenfunktion?

139

Ich habe versucht, den Grund für Konstanten in Java zu identifizieren. Ich habe erfahren, dass Java es uns ermöglicht, Konstanten mithilfe von finalSchlüsselwörtern zu deklarieren .

Meine Frage ist, warum Java keine Constant ( const) -Funktion eingeführt hat. Da viele Leute sagen, dass es aus C ++ stammt, haben wir in C ++ ein constSchlüsselwort.

Bitte teilen Sie Ihre Gedanken.

gmhk
quelle
2
Es gibt ein constSchlüsselwort, aber keine zugrunde liegende Funktion. Titel und Tags wurden entsprechend korrigiert.
Marquis von Lorne

Antworten:

141

Jedes Mal, wenn ich von schwerer C ++ - Codierung zu Java wechsle, brauche ich eine Weile, um mich an die mangelnde Konstanz in Java anzupassen . Diese Verwendung vonconst in C ++ unterscheidet sich stark von der Deklaration konstanter Variablen, wenn Sie es nicht wussten. Im Wesentlichen wird sichergestellt, dass ein Objekt unveränderlich ist, wenn über einen speziellen Zeigertyp namens const-pointer zugegriffen wird. In Java gebe ich an Orten, an denen ich normalerweise einen const-Zeiger zurückgeben möchte, stattdessen eine Referenz mit einem Schnittstellentyp zurück enthält nur Methoden, die keine Nebenwirkungen haben sollten. Leider wird dies von der Sprache nicht erzwungen.

Wikipedia bietet folgende Informationen zu diesem Thema:

Interessanterweise betrachtet die Java-Sprachspezifikation const als reserviertes Schlüsselwort - dh eines, das nicht als Variablenbezeichner verwendet werden kann -, weist ihm jedoch keine Semantik zu. Es wird angenommen, dass die Reservierung des Schlüsselworts stattgefunden hat, um eine Erweiterung der Java-Sprache zu ermöglichen, um C ++ - const-Methoden und einen Zeiger auf den const-Typ einzuschließen. Das Erweiterungsanforderungsticket im Java-Community-Prozess zur Implementierung der Konstantenkorrektheit in Java wurde 2005 geschlossen, was bedeutet, dass die Konstantenkorrektheit wahrscheinlich nie in die offizielle Java-Spezifikation gelangen wird.

Revolverheld47
quelle
10
Java finalist jedoch ähnlich.
Reinierpost
62
Nein, ist es nicht. finalMethode zum Beispiel arbeiten völlig anders als C ++ - constMethoden.
Dom0
7
@reinierpost Das finalSchlüsselwort für Eigenschaften oder Variablen stellt nur sicher, dass eine Eigenschaft oder Variable nur einmal zugewiesen wird . Man könnte den Zustand dieses Objekts immer noch ändern, indem man beispielsweise eine Methode mit Nebenwirkungen aufruft. finalähnelt in gewisser Weise der Stapelzuweisung von C ++ in Bezug auf die Bezugnahme auf ein Objekt und nicht auf einen Zeiger, aber das ist alles. Dies ist natürlich zusätzlich zu dem, was dom0 bereits gesagt hat.
Tim
9
finalin Java scheint wie C ++ constfür Werttypen zu funktionieren , aber eher wie eine C ++ Nicht-Konstante T&für Referenztypen
Mark K Cowan
1
final ist ein schizophrenes Schlüsselwort. Es verhindert zwar eine Neuzuweisung, wird jedoch auch verwendet, um Variablen Schließungen auszusetzen. Ich möchte möglicherweise eine Neuzuweisung verhindern, diese Variablen jedoch nicht verfügbar machen, aber es gibt keine Möglichkeit, dies zu tun. Es ist meiner Meinung nach eine ziemlich schlecht durchdachte Sprachfunktion.
David Bradley
82

Was bedeutet? constStellen Sie zunächst fest
, dass die Semantik eines "const" -Schlüsselworts für verschiedene Personen unterschiedliche Bedeutungen hat:

  • Schreibgeschützte Referenz - Java- finalSemantik - Referenzvariable selbst kann nicht neu zugewiesen werden, um auf eine andere Instanz (Speicherort) zu verweisen, aber die Instanz selbst kann geändert werden
  • Nur lesbare Referenz - C- constZeiger / Referenzsemantik - bedeutet, dass diese Referenz nicht zum Ändern der Instanz verwendet werden kann (z. B. kann Instanzvariablen nicht zugewiesen werden, kann keine veränderbaren Methoden aufrufen) - wirkt sich nur auf die Referenzvariable aus, sodass eine nicht konstante Referenz auf die verweist Dieselbe Instanz könnte die Instanz ändern
  • Unveränderliches Objekt - bedeutet, dass die Instanz selbst nicht geändert werden kann - gilt für die Instanz, sodass eine nicht konstante Referenz nicht zulässig ist oder nicht zum Ändern der Instanz verwendet werden kann
  • eine Kombination der oben genannten ?
  • andere ?

Warum oder warum nichtconst
Zweitens, wenn Sie sich wirklich mit einigen der Argumente "pro" vs "con" befassen möchten, lesen Sie die Diskussion unter diesem "Bug for Enhancement (RFE)" Bug ". Diese RFE fordert eine Funktion "const" vom Typ "Nur lesbare Referenz" an. Das 1999 eröffnete und 2005 von Sun geschlossene / abgelehnte Thema "const" wurde heftig diskutiert:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070

Obwohl es auf beiden Seiten viele gute Argumente gibt, sind einige der oft zitierten (aber nicht unbedingt zwingenden oder eindeutigen) Gründe dagegen const:

  • kann verwirrende Semantik haben, die missbraucht und / oder missbraucht werden kann (siehe Was constbedeutet oben)
  • kann ansonsten verfügbare Funktionen duplizieren (z. B. Entwerfen einer unveränderlichen Klasse unter Verwendung einer unveränderlichen Schnittstelle)
  • Dies kann ein Kriechen von Merkmalen sein, was dazu führt, dass andere semantische Änderungen erforderlich sind, z. B. die Unterstützung für die Übergabe von Objekten nach Wert

Bevor jemand versucht, mich darüber zu diskutieren, ob dies gute oder schlechte Gründe sind, beachten Sie, dass dies nicht meine Gründe sind . Sie sind einfach der "Kern" einiger der Gründe, die ich aus dem Überfliegen der RFE-Diskussion gezogen habe. Ich stimme ihnen nicht unbedingt selbst zu - ich versuche nur zu zitieren, warum manche Leute (nicht ich) der Meinung sind, dass ein constKeyword keine gute Idee ist. Persönlich würde ich es lieben, wenn mehr "const" -Semantik eindeutig in die Sprache eingeführt würde.

Bert F.
quelle
2
+1 nur für den zweiten Teil Ihrer Antwort. Viele, viele Schlüsselwörter haben eine nicht triviale Semantik. Ist das volatileso einfach zu verstehen? Oder final? Meh.
Einpoklum
OTOH, Java wurde entwickelt, um so wenige dieser nicht trivialen Funktionen wie möglich zu verwenden. Und ich sage nicht, dass sie dieses Ziel erreicht haben (oder dass Java nicht von diesem Ziel abgewichen ist). Aber es aus diesem Grund auszuschließen, mag immer noch Verdienst gehabt haben. Dass es andere komplizierte Dinge gibt, ist umso mehr ein Grund, nicht mehr einzuführen (oder Sie würden mit der D-Sprache enden).
Maarten Bodewes
7

const in C ++ bedeutet nicht, dass ein Wert eine Konstante ist.

const in C ++ bedeutet, dass der Kunde eines Vertrags verpflichtet ist, seinen Wert nicht zu ändern.

Ob sich der Wert eines constAusdrucks ändert, wird deutlicher, wenn Sie sich in einer Umgebung befinden, die threadbasierte Parallelität unterstützt.

Da Java von Anfang an so konzipiert wurde, dass es die Parallelität von Threads und Sperren unterstützt, trug es nicht zur Verwirrung bei, indem der Begriff überladen wurde, um die Semantik zu haben, die vorhanden finalist.

z.B:

#include <iostream>

int main ()
{
    volatile const int x = 42;

    std::cout << x << std::endl;

    *const_cast<int*>(&x) = 7;

    std::cout << x << std::endl;

    return 0;
}

Ausgänge 42 dann 7.

Obwohl xmarkiert const, da ein nicht xkonstanter Alias ​​erstellt wird, ist dies keine Konstante. Nicht jeder Compiler benötigt volatiledieses Verhalten (obwohl jeder Compiler die Konstante einbinden darf).

Bei komplizierteren Systemen erhalten Sie Konstanten- / Nicht-Konstanten-Aliase ohne Verwendung von. const_castDaher wird es immer gefährlicher, sich vorzustellen, dass Konstante bedeutet, dass sich etwas nicht ändert. constbedeutet lediglich, dass Ihr Code ihn nicht ohne Umwandlung ändern kann, nicht, dass der Wert konstant ist.

Pete Kirkham
quelle
3
const int x = 42; - x ist eine Konstante
2
@Neil Wenn Sie ein Objekt oder eine Variable haben, die sowohl durch const- als auch durch nicht-const-Zeiger aliasiert ist, kann der Wert des const-Alias ​​durch den nicht-const-Alias ​​geändert werden. Daher constbedeutet dies nicht, dass ein Wert konstant ist. Dies bedeutet, dass der Client eines Werts gezwungen ist, ihn nicht zu mutieren. In Ihrem Beispiel gibt es keinen Alias, sodass alle Benutzer derselben Einschränkung unterliegen. Dies ist im Allgemeinen nicht der Fall. constwirkt sich auf die Kunden aus, nicht auf den Wert - es heißt, Sie können ihn nicht ändern, nicht, dass er sich nicht ändert.
Pete Kirkham
1
Konst-Korrektheit ist über das, was der Programmierer sollte tun, nicht , was sie tun können . Ich denke, Sie scheinen alle diesen Punkt verstanden zu haben. Ich wollte nur ein paar Cent hinzufügen, die für den kausalen Leser von Interesse sein könnten: Designmuster wie das immutable interfaceund immutable objectsind eine andere Möglichkeit (mit Besetzung und Reflexion zu schlagen), um const in Java nachzuahmen. "True" const kann mit SealedObject ausgeführt werden , leider zerstört es den Anwendungsfall unseres Objekts.
Martin Andersson
6
Man sollte beachten, dass das Ergebnis Ihres Programms undefiniert ist. const_cast dient nicht zum Ändern von const-Variablen, sondern zum Übergeben von const-Variablen an APIs, die nicht const-korrekt sind, aber auch den Wert nicht ändern. Ich denke, die Gewohnheit zu denken, dass sich etwas const nicht ändern wird, ist gut, denn wenn sie sich ändern, bedeutet dies, dass Ihr Programm Hacks enthält, die je nach verwendetem Compiler jederzeit unterbrochen werden können.
Cygon
1
Das Ändern eines konstanten Werts ist ein undefiniertes Verhalten. Ihre Festplatte ist möglicherweise bereits formatiert.
Zhe Yang
5

Dies ist eine alte Frage, aber ich dachte, ich würde trotzdem meine 2 Cent beisteuern, da dieser Thread heute im Gespräch auftauchte.

Dies antwortet nicht genau, warum es keine Konstante gibt. aber wie Sie Ihre Klassen unveränderlich machen. (Leider habe ich noch nicht genug Ruf, um als Kommentar zur akzeptierten Antwort zu posten)

Um die Unveränderlichkeit eines Objekts zu gewährleisten, müssen Sie Ihre Klassen sorgfältiger gestalten, damit sie unveränderlich sind. Dies erfordert etwas mehr Sorgfalt als eine veränderbare Klasse.

Dies geht zurück auf Josh Blochs effektives Java- Element 15 - Mutabilität minimieren . Wenn Sie das Buch nicht gelesen haben, nehmen Sie eine Kopie und lesen Sie sie einige Male durch. Ich garantiere, dass es Ihr figuratives "Java-Spiel" verbessern wird .

In Punkt 15 schlägt Bloch vor, die Veränderbarkeit von Klassen einzuschränken, um den Status des Objekts sicherzustellen.

Um das Buch direkt zu zitieren:

Eine unveränderliche Klasse ist einfach eine Klasse, deren Instanzen nicht geändert werden können. Alle in jeder Instanz enthaltenen Informationen werden beim Erstellen bereitgestellt und sind für die Lebensdauer des Objekts festgelegt. Die Java-Plattformbibliotheken enthalten viele unveränderliche Klassen, einschließlich String, die primitiven Box-Klassen sowie BigInteger und BigDecimal. Dafür gibt es viele gute Gründe: Unveränderliche Klassen sind einfacher zu entwerfen, zu implementieren und zu verwenden als veränderbare Klassen. Sie sind weniger fehleranfällig und sicherer.

Bloch beschreibt dann, wie Sie Ihre Klassen unveränderlich machen, indem Sie 5 einfache Regeln befolgen:

  1. Geben Sie keine Methoden an, die den Status des Objekts ändern (z. B. Setter, auch Mutatoren genannt ).
  2. Stellen Sie sicher, dass die Klasse nicht erweitert werden kann (dies bedeutet, dass die Klasse selbst als deklariert wird final).
  3. Machen Sie alle Felder final.
  4. Machen Sie alle Felder private.
  5. Stellen Sie den exklusiven Zugriff auf veränderbare Komponenten sicher. (durch defensive Kopien der Objekte)

Für weitere Informationen empfehle ich dringend, eine Kopie des Buches abzuholen.

Grego
quelle
3
const in C ++ ist VIEL flexibler als die vollständige Unveränderlichkeit. In gewissem Sinne kann 'const' als 'unveränderlich in diesem speziellen Kontext' angesehen werden. Beispiel: Ich habe eine Klasse, die nicht unveränderlich ist, ABER ich möchte sicherstellen, dass sie nicht über bestimmte öffentliche APIs geändert wird. Das Erstellen einer Schnittstelle (und das Zurückgeben für diese öffentliche API), wie von Gunslinger47 vorgeschlagen, bewirkt dasselbe in Java, aber Junge - es ist hässlich (und daher wird es von den meisten Java-Entwicklern ignoriert, was zu erheblichem unnötigem Durcheinander führt). .
No-Bugs Hare
3

Die C ++ - Semantik von unterscheidet constsich stark von Java final. Wenn die Designer verwendet hätten const, wäre es unnötig verwirrend gewesen.

Die Tatsache, dass constes sich um ein zurückhaltendes Wort handelt, deutet darauf hin, dass die Designer Ideen für die Implementierung hatten const, sich aber inzwischen dagegen entschieden haben. siehe diesen geschlossenen Fehler . Zu den genannten Gründen gehört, dass das Hinzufügen von Unterstützung für den C ++ - Stil constzu Kompatibilitätsproblemen führen würde.

Stephen C.
quelle
-1

Es gibt eine Möglichkeit, "const" -Variablen in Java zu erstellen, jedoch nur für bestimmte Klassen. Definieren Sie einfach eine Klasse mit endgültigen Eigenschaften und unterordnen Sie sie. Verwenden Sie dann die Basisklasse, in der Sie "const" verwenden möchten. Wenn Sie "const" -Methoden verwenden müssen, fügen Sie diese ebenfalls der Basisklasse hinzu. Der Compiler erlaubt Ihnen nicht, die seiner Meinung nach endgültigen Methoden der Basisklasse zu ändern, sondern liest und ruft Methoden in der Unterklasse auf.

user1122069
quelle
Können Sie bitte ein Beispiel dafür nennen?
NO_NAME
Klasse MYString implementiert GetString {private final String aaaa; public String getString (); } Klasse MutableString implementiert GetString {private String aaaa2; public String getString (); public String setString ()}
user1122069
-2

Es gibt zwei Möglichkeiten, Konstanten zu definieren - constund zwar static finalmit genau derselben Semantik. Des Weiteren static finalbeschreibt das Verhalten besser alsconst

Bozho
quelle
@Bozho, du hast gesagt, besseres Verhalten als Const, wie ist es? können Sie ein Beispiel teilen
gmhk
Nun, die Variable ist static(gehört nicht zu einer bestimmten Instanz) und final- kann nicht geändert werden.
Bozho
-2

Sie können static final verwenden, um etwas zu erstellen, das Const ähnelt. Ich habe dies in der Vergangenheit verwendet.

protected static final int cOTHER = 0;
protected static final int cRPM = 1;
protected static final int cSPEED = 2;
protected static final int cTPS = 3;
protected int DataItemEnum = 0;

public static final int INVALID_PIN = -1;
public static final int LED_PIN = 0;
hamish
quelle
Für die Gerüchte-optimierte Optimierung abgelehnt, weil ich ein Gerücht gehört habe, dass dies eine ineffektive Strategie ist.
afarley
Ich habe das Gerücht aus der Antwort entfernt. Sie können weiterhin static final int verwenden, um Code im Const-Stil zu erstellen.
Hamish
Ok, ich habe meine Ablehnung entfernt. Vielleicht beziehen sich einige der anderen Abstimmungen auf die switch-Anweisung (was hat das mit dem Rest Ihres Beispiels zu tun?)
Uhr
In der switch-Anweisung habe ich das cRPM so verwendet, als wäre es eine const. ganz richtig, wenn man das oben Gesagte bedenkt. also ja ich habe den schalter entfernt.
Hamish