2016-08-23 2 views
-1

Betrachten Sie den Code untenWarum Java-Compiler nicht Praktikanten Arrays?

String s1 = "testString"; 
String s2 = "testString"; 
if(s1 == s2)System.out.println("equals!"); 

it !, druckt gleich (ich bin mir dessen bewusst String vom Compiler Internierung)

String[] s1 = {"testString","teststring2"}; 
String[] s2 = {"testString","teststring2"}; 
if(s1 == s2)System.out.println("equals!"); 

jedoch der obige Code funktioniert nicht, warum Java-Compiler nicht intern tut Zeichenfolgenarray?

+0

Da Interning ist nur für 'String's. –

+0

Sie könnten diese Frage zu ** jedem ** anderen Typ im Java-Ökosystem stellen. –

+4

Arrays sind nicht unveränderbar. Es wäre sehr problematisch, sie alle automatisch zu internieren. – khelwood

Antwort

4

Der Grund ist, dass ein String unveränderlich ist. Sie können es nicht ändern, ohne eine neue Instanz zu erstellen. Es ist also sicher, dieselbe Instanz zu verwenden, wo immer es für übereinstimmende Zeichenfolgen möglich ist. Strings are constant; their values cannot be changed after they are created.

Wie auch immer Arrays sind eine andere Geschichte. Sie können ein Array ändern, indem Sie einem der Felder einen neuen Wert zuweisen.

s1[0] = "testString3" 

Wenn der Compiler die gleiche Instanz für s1 verwenden würden und s2 Sie würden atomatically beide Arrays ändern. Und das ist wahrscheinlich nicht etwas, was Sie tun möchten. Das ist der Grund, warum Arrays nicht interniert sind.

Bitte beachten Sie auch, dass die String-Internierung je nach Compiler Einschränkungen aufweisen kann und dass der Compiler eventuell einige Strings intern nicht pausiert, je nachdem wie viele Strings es gibt oder wie lang die Strings sind. Es gibt eine interne Zeichenkettentabelle, die von der JVM-Option +XX:StringTableSize=n gesteuert wird, die die Größe der Zeichenkettentabelle bestimmt, die zum Speichern interner Zeichenketten verwendet wird.

Wenn es darauf ankommt, Strings zu vergleichen, ist es immer besser, die Gleichheitsfunktionen zu verwenden. Die meisten Implementierungen überprüfen zuerst die Referenzgleichheit, bevor sie teurere Überprüfungen durchführen.

EDIT:

Also eigentlich meine Behauptung, dass die Lagerung von internierten Strings wächst voll scheint falsch zu sein. Die Dokumentation der String.intern()-Methode zeigt an, dass diese Funktion sicherstellen wird, dass die Zeichenfolge dem Pool eindeutiger Zeichenfolgen hinzugefügt wird. Bedeutet, dass es keinen Weg gibt, dass dieser Pool voll sein wird. @Holger schrieb, dass die interne Implementierung eine Hash-Map-ähnliche Struktur irgendeiner Art verwendet. Dies unterstützt diesen Anspruch.

Also wird die JVM alle konstanten Strings in der intern gespeicherten Hash-Tabelle nach JLS §3.10.5 speichern.

Ein String-Literal bezieht sich immer auf dieselbe Instanz der Klasse String. Dies liegt daran, Stringliterale - oder, allgemeiner, Strings, die die Werte der konstanten Ausdrücke sind ... - „interniert“ werden, um eindeutige Instanzen zu teilen, wobei das Verfahren String.intern

mit

dass alle gesagt, bitte gewöhnen Sie sich noch an die Methode equals der String-Klasse, um Strings auf Gleichheit zu prüfen. Das Verfahren wird die Tatsache ausnutzen, dass die Zeichenfolgen die gleiche Referenz sein können und in diesem Fall sehr schnell vervollständigt werden können, bevor eine teurere Längen- und Zeichenüberprüfung durchgeführt wird. Es ist immer besser, diese Methode zu verwenden. Die Art und Weise, wie Strings behandelt werden, kann sich in zukünftigen Versionen von Java ändern oder nicht. Mit der equals Methode sind Sie auf der sicheren Seite.

+1

Das ist nicht wirklich die Erklärung dafür, warum nur Strings interniert werden - es gibt viele andere unveränderlich herumschwimmende Typen. –

+0

das macht sehr viel Sinn, danke: D – Arthas

+0

@OliverCharlesworth Nennen Sie einen mit einer tiefen Compiler-Integration wie 'string'. – Nitram

Verwandte Themen