2016-11-16 1 views
0

Durch das Lesen Oracle JVM-Architektur Dokument:JVM-Architektur: Laufzeitkonstante Pool in Bereich Methode ist pro-Klasse

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html

Ein Laufzeitkonstante Pool ist eine pro-Klasse oder pro-Schnittstelle Lauf -time Darstellung der Tabelle constant_pool in einer Klassendatei (§4.4).

Ich verstehe, dass für jede Klasse , hat es eine Laufzeit konstant Pool hat (bitte korrigiert mich wenn ich falsch liege).

Allerdings, was ich verwirrt bin, ist, dass, wenn ich zwei verschiedene Klassen A und B habe und jede Klasse hat eine private String-Variable sagen String value = "abc".

wenn ich vergleiche A.value mit B.value== mit eher als equals, werde ich ein true bekommen, die ich denke, dass "abc" sowohl in A und B in dem gleichen Laufzeit konstant Pool sind? Kann mir jemand zeigen, wo ich falsch liege?

+0

können Sie das Dokument verknüpfen? –

+0

@JigarJoshi verbunden –

+0

Wenn beide privat sind, wie greifen Sie beide gleichzeitig auf, um sie zu vergleichen? Erstellt man eine Instanz des anderen? Können Sie Ihren vollständigen Code posten? – Andrew

Antwort

3

Dies ist eine präemptive Optimierung, die die JLS überlagert.

Von JLS 7, §3.10.5 (Formatierung Mine)

Darüber hinaus ist ein Stringliteral bezieht sich immer auf die gleiche Instanz der Klasse String. Dies liegt daran, dass Zeichenfolgenliterale - oder allgemeiner Zeichenfolgen, bei denen es sich um die Werte von Konstantenausdrücken handelt - (§15.28) - interniert sind, um eindeutige Instanzen mit der Methode String.intern gemeinsam nutzen zu können.

Beachten Sie jedoch, dass dies nur für String-Literale und konstante Ausdrücke gilt. Dynamisch konstruierte Zeichenfolgen (z. B. x + y für Zeichenfolgen x und y) werden nicht automatisch interniert, um die gleichen eindeutigen Instanzen zu teilen. Daher müssen Sie immer .equals im Allgemeinen verwenden, außer Sie können garantieren, dass Ihre Operanden konstante Ausdrücke sind.

1

Dies liegt daran, dass '==' Verweise vergleicht. Objekte von A und B haben unterschiedliche String-Wert-Variablen (und daher hat jeder Klassen-Konstanten-Pool einen separaten Eintrag dafür); aber sie sind beide auf den gleichen Wert initialisiert. Der Compiler/JVM optimiert höchstwahrscheinlich für den Raum, indem er beide auf den gleichen Kompilierzeitkonstantenwert im Bytecode zeigt. Der '==' Operator vergleicht keine konstanten Pool-Positionen.

Edit: um einige Verwirrung zu klären, bedeutet dies NICHT, dass "==" für den String-Vergleich verwendet werden kann. Alles, was ich sagte, war, dass es nicht verwendet werden kann, um den Standort des konstanten Pools zu vergleichen. Es ist nur für eine Sache und eins: zu vergleichen, ob zwei Referenzen auf dasselbe Objekt zeigen. Die Situation in der Frage führt zu SOMETIMES == Wahr, aber manchmal nicht. Es hängt von Entscheidungen ab, die der Compiler und JVM treffen (oder abhängig davon, was die JSL sagt, wie ein scharfsinniger Beantworter gesagt hat).

+0

Bedeutet das, dass es immer sicher ist, "==" für den Stringvergleich zu verwenden? –

+0

@GuifanLi NEIN! Der Operator "==" vergleicht, ob zwei Referenzen auf denselben Wert zeigen. Wenn ein Programm die Zeichenfolge "abc" aus einer Datei liest, würde die Variable, auf die es zeigt, NICHT == diesen Wert haben. Sie wären jedoch gleich. – Andrew