- Як я можу змусити CaseInsensitiveString поводитися як String, щоб наведене вище твердження було нормальним (з і без розширення рядка)? Що саме в рядку робить нормальним можливість просто передавати його таким літералом? З мого розуміння, в Java немає концепції "конструктора копій", чи не так?
Досить було сказано з першого пункту. "Польська" - це рядковий літерал, який не може бути присвоєний класу CaseInsentiviveString.
Тепер про другий момент
Незважаючи на те, що ви не можете створювати нові літерали, ви можете слідувати першому пункту цієї книги для "подібного" підходу, тому наступні твердження відповідають дійсності:
CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");
assert cis5 == cis6;
assert cis5.equals(cis6);
Ось код.
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();
}
// Перевірте клас, використовуючи ключове слово "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>
Тобто створити внутрішній пул об’єктів CaseInsensitiveString і повернути звідти екземпляр кореспонденції.
Таким чином, оператор "==" повертає true для двох посилань на об'єкти, що представляють одне і те ж значення .
Це корисно, коли подібні об'єкти використовуються дуже часто, а створення витрат є дорогим.
Документація рядкового класу стверджує, що клас використовує внутрішній пул
Клас не є повним, деякі цікаві проблеми виникають, коли ми намагаємося пройти вміст об’єкта при реалізації інтерфейсу CharSequence, але цей код досить хороший, щоб показати, як цей елемент у Книзі можна застосувати.
Важливо зауважити, що за допомогою об’єкта internalPool посилання не звільняються і, отже, не можна збирати сміття, і це може стати проблемою, якщо створено багато об’єктів.
Це працює для класу String, оскільки він інтенсивно використовується, і пул складається лише з "інтернованого" об'єкта.
Це добре працює і для булевого класу, оскільки є лише два можливих значення.
І нарешті, це також причина, чому valueOf (int) у класі Integer обмежується значеннями від -128 до 127 int.