2014-09-10 6 views
7

Ich habe eine ziemlich seltsame Sache bei der Arbeit mit Java gefunden. Vielleicht ist es eine gewöhnliche Sache, aber ich verstehe nicht, warum es so funktioniert.Java. Warum funktioniert das bei englischen und slawischen Charakteren anders?

Ich habe einen Code wie folgt:

Character x = 'B'; 
Object o = x; 
System.out.println(o == 'B'); 

Es funktioniert gut, und der Ausgang ist "true". Dann wechsle ich das Englisch B zu slawische B (Б):

Character x = 'Б'; 
Object o = x; 
System.out.println(o == 'Б'); 

Nun ist der Ausgang "false". Woher? Übrigens, die Ausgabe ist immer noch "wahr", wenn ich die Variable x direkt mit 'Á' vergleiche, aber wenn ich es durch ein Objekt mache, funktioniert es anders.

Kann jemand bitte dieses Verhalten erklären?

Antwort

8

Ohne Boxen - mit nur char - wäre alles in Ordnung. Ebenso, wenn Sie equals anstelle von == verwenden, würden Sie in Ordnung sein. Das Problem besteht darin, dass Sie Verweise für umrahmte Werte mithilfe von == vergleichen, bei dem nur nach einer Referenzidentität gesucht wird. Sie sehen einen Unterschied aufgrund der Funktionsweise von Auto-Boxing. Sie können die gleiche Sache mit Integer sehen:

Object x = 0; 
Object y = 0; 
System.out.println(x == y); // Guaranteed to be true 

Object x = 10000; 
Object y = 10000; 
System.out.println(x == y); // *May* be true 

Grundsätzlich „kleinen“ Werte haben boxed Darstellungen zwischengespeichert, während „größer“ Werte können nicht.

Von JLS 5.1.7:

Wenn der Wert p geschachtelt ist eine ganze Zahl vom Typ Literal int zwischen -128 und 127 inclusive (§3.10.1) oder die Boolesche literal wahr oder falsch (§3.10. 3), oder ein Zeichenliteral zwischen '\ u0000' und '\ u007f' inklusive (§3.10.4), dann seien a und b die Ergebnisse von zwei Boxenkonvertierungen von p. Es ist immer so, dass a == b.

Im Idealfall würde das Boxen eines primitiven Werts immer eine identische Referenz ergeben. In der Praxis ist dies unter Verwendung bestehender Implementierungstechniken möglicherweise nicht durchführbar. Die obige Regel ist ein pragmatischer Kompromiss, der erfordert, dass bestimmte allgemeine Werte immer in nicht unterscheidbare Objekte eingereiht werden. Die Implementierung kann diese faul oder eifrig zwischenspeichern. Für andere Werte lässt die Regel keine Annahmen über die Identität der Boxed-Werte auf Seiten des Programmierers zu. Dies ermöglicht (aber nicht unbedingt) die gemeinsame Nutzung einiger oder aller dieser Referenzen. Beachten Sie, dass Ganzzahlliterale vom Typ long zulässig, aber nicht erforderlich sind, um sie gemeinsam nutzen zu können.

Dies stellt sicher, dass das Verhalten in den meisten Fällen das gewünschte ist, ohne dass dies zu einer übermäßigen Leistungseinbuße führt, insbesondere bei kleinen Geräten. Weniger speicherbegrenzte Implementierungen könnten beispielsweise alle Werte zwischen char und short sowie int und long im Bereich von -32K bis +32K zwischenspeichern.

Der Teil über „ein Zeichenliteral zwischen \u0000 and \ u007f`“ garantiert, dass ASCII-Zeichen eingerahmt im Cache gespeichert werden, aber nicht nicht-ASCII-Zeichen eingerahmt.

2

wenn Sie das tun

Character x = 'B' 

es Character.valueOf(C)

2: invokestatic #16     // Method java/lang/Character.valueOf:(C)Ljava/lang/Character; 

die

Diese Methode wird immer Cache-Werte im Bereich '\ u0000' Caches ruft zu '\ u007F' einschließlich und kann andere Werte außerhalb dieses Bereichs zwischenspeichern.

public static Character valueOf(char c) { 
    if(c <= 127) { // must cache 
     return CharacterCache.cache[(int)c]; 
    } 
    return new Character(c); 
} 

ähnliche

Verwandte Themen