- ¿Cómo hago para que CaseInsensitiveString se comporte como String para que la declaración anterior esté bien (con y sin extender String)? ¿Qué tiene String que hace que esté bien poder pasarle un literal como ese? Según tengo entendido, no existe el concepto de "constructor de copias" en Java, ¿verdad?
Ya se ha dicho suficiente desde el primer punto. "Polaco" es un literal de cadena y no se puede asignar a la clase CaseInsentiviveString.
Ahora sobre el segundo punto
Aunque no puede crear nuevos literales, puede seguir el primer elemento de ese libro para un enfoque "similar", de modo que las siguientes declaraciones sean verdaderas:
CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");
assert cis5 == cis6;
assert cis5.equals(cis6);
Aquí está el código.
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;
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 );
}
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();
}
// Prueba la clase usando la palabra clave "assert"
public static void main( String [] args ) {
CaseInsensitiveString cis1 = new CaseInsensitiveString("Polish");
CaseInsensitiveString cis2 = new CaseInsensitiveString("Polish");
assert cis1 != cis2;
assert cis1.equals(cis2);
CaseInsensitiveString cis3 = CaseInsensitiveString.valueOf("Polish");
CaseInsensitiveString cis4 = CaseInsensitiveString.valueOf("Polish");
assert cis3 == cis4;
assert cis3.equals(cis4);
CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");
assert cis5 == cis6;
assert cis5.equals(cis6);
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>
Es decir, cree un grupo interno de objetos CaseInsensitiveString y devuelva la instancia correspondiente desde allí.
De esta manera, el operador "==" devuelve verdadero para dos referencias de objetos que representan el mismo valor .
Esto es útil cuando se utilizan objetos similares con mucha frecuencia y la creación de costes es cara.
La documentación de la clase de cadena indica que la clase usa un grupo interno
La clase no está completa, surgen algunos problemas interesantes cuando intentamos recorrer el contenido del objeto al implementar la interfaz CharSequence, pero este código es lo suficientemente bueno para mostrar cómo se podría aplicar ese elemento en el Libro.
Es importante notar que al usar el objeto internalPool , las referencias no se liberan y, por lo tanto, no se pueden recolectar como basura, y eso puede convertirse en un problema si se crean muchos objetos.
Funciona para la clase String porque se usa de forma intensiva y el grupo está constituido únicamente por objetos "internos".
También funciona bien para la clase booleana, porque solo hay dos valores posibles.
Y finalmente, esa es también la razón por la que valueOf (int) en la clase Integer está limitado a valores de -128 a 127 int.