- Wie kann ich CaseInsensitiveString wie String verhalten, damit die obige Anweisung in Ordnung ist (mit und ohne Erweiterung des Strings)? Was ist es an String, das es in Ordnung macht, es einfach so wörtlich weitergeben zu können? Nach meinem Verständnis gibt es in Java kein "Kopierkonstruktor" -Konzept, oder?
Vom ersten Punkt an wurde genug gesagt. "Polnisch" ist ein Zeichenfolgenliteral und kann nicht der CaseInsentiviveString-Klasse zugewiesen werden.
Nun zum zweiten Punkt
Obwohl Sie keine neuen Literale erstellen können, können Sie dem ersten Punkt dieses Buches für einen "ähnlichen" Ansatz folgen, sodass die folgenden Aussagen zutreffen:
// Lets test the insensitiveness
CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");
assert cis5 == cis6;
assert cis5.equals(cis6);
Hier ist der Code.
C:\oreyes\samples\java\insensitive>type CaseInsensitiveString.java
import java.util.Map;
import java.util.HashMap;
public final class CaseInsensitiveString {
private static final Map<String,CaseInsensitiveString> innerPool
= new HashMap<String,CaseInsensitiveString>();
private final String s;
// Effective Java Item 1: Consider providing static factory methods instead of constructors
public static CaseInsensitiveString valueOf( String s ) {
if ( s == null ) {
return null;
}
String value = s.toLowerCase();
if ( !CaseInsensitiveString.innerPool.containsKey( value ) ) {
CaseInsensitiveString.innerPool.put( value , new CaseInsensitiveString( value ) );
}
return CaseInsensitiveString.innerPool.get( value );
}
// Class constructor: This creates a new instance each time it is invoked.
public CaseInsensitiveString(String s){
if (s == null) {
throw new NullPointerException();
}
this.s = s.toLowerCase();
}
public boolean equals( Object other ) {
if ( other instanceof CaseInsensitiveString ) {
CaseInsensitiveString otherInstance = ( CaseInsensitiveString ) other;
return this.s.equals( otherInstance.s );
}
return false;
}
public int hashCode(){
return this.s.hashCode();
}
// Teste die Klasse mit dem Schlüsselwort "assert"
public static void main( String [] args ) {
// Creating two different objects as in new String("Polish") == new String("Polish") is false
CaseInsensitiveString cis1 = new CaseInsensitiveString("Polish");
CaseInsensitiveString cis2 = new CaseInsensitiveString("Polish");
// references cis1 and cis2 points to differents objects.
// so the following is true
assert cis1 != cis2; // Yes they're different
assert cis1.equals(cis2); // Yes they're equals thanks to the equals method
// Now let's try the valueOf idiom
CaseInsensitiveString cis3 = CaseInsensitiveString.valueOf("Polish");
CaseInsensitiveString cis4 = CaseInsensitiveString.valueOf("Polish");
// References cis3 and cis4 points to same object.
// so the following is true
assert cis3 == cis4; // Yes they point to the same object
assert cis3.equals(cis4); // and still equals.
// Lets test the insensitiveness
CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");
assert cis5 == cis6;
assert cis5.equals(cis6);
// Futhermore
CaseInsensitiveString cis7 = CaseInsensitiveString.valueOf("SomethinG");
CaseInsensitiveString cis8 = CaseInsensitiveString.valueOf("someThing");
assert cis8 == cis5 && cis7 == cis6;
assert cis7.equals(cis5) && cis6.equals(cis8);
}
}
C:\oreyes\samples\java\insensitive>javac CaseInsensitiveString.java
C:\oreyes\samples\java\insensitive>java -ea CaseInsensitiveString
C:\oreyes\samples\java\insensitive>
Erstellen Sie also einen internen Pool von CaseInsensitiveString-Objekten und geben Sie von dort aus die entsprechende Instanz zurück.
Auf diese Weise gibt der Operator "==" true für zwei Objektreferenzen zurück, die denselben Wert darstellen .
Dies ist nützlich, wenn ähnliche Objekte sehr häufig verwendet werden und das Erstellen von Kosten teuer ist.
In der Dokumentation zur Zeichenfolgenklasse wird angegeben, dass die Klasse einen internen Pool verwendet
Die Klasse ist nicht vollständig. Einige interessante Probleme treten auf, wenn wir versuchen, den Inhalt des Objekts bei der Implementierung der CharSequence-Schnittstelle zu durchlaufen. Dieser Code ist jedoch gut genug, um zu zeigen, wie dieses Element im Buch angewendet werden kann.
Es ist wichtig zu beachten, dass bei Verwendung des internalPool- Objekts die Referenzen nicht freigegeben werden und somit kein Müllsammelobjekt ist. Dies kann zu einem Problem werden, wenn viele Objekte erstellt werden.
Es funktioniert für die String-Klasse, da es intensiv genutzt wird und der Pool nur aus "internierten" Objekten besteht.
Es funktioniert auch gut für die Boolesche Klasse, da es nur zwei mögliche Werte gibt.
Und schließlich ist dies auch der Grund, warum valueOf (int) in der Klasse Integer auf -128 bis 127 int-Werte beschränkt ist.