String
специальный встроенный класс языка. Это для String
класс [только 119], в которых необходимо постараться не говорить
String s = new String("Polish");
, поскольку литерал "Polish"
уже имеет тип String
, и Вы создаете дополнительный лишний объект. Для любого другого класса, говоря
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
корректное (и только, в этом случае) вещь сделать.
В большинстве версий JDK эти две версии будут тем же:
Строка s = новая ("глупая") Строка;
Строка s = "Больше глупый";
, поскольку строки неизменны, компилятор ведет список строковых констант и при попытке сделать новый, то сначала проверит, чтобы видеть, определяется ли строка уже. Если это - тогда ссылка на существующую неизменную строку, возвращается.
Для разъяснения - при высказывании "Строки s =" Вы определяете новую переменную, которая занимает место на стеке - тогда, не говорите ли Вы "Больше глупую" или новую Строку ("глупую") точно, то же самое происходит - новая постоянная строка компилируется в Ваше приложение и контрольные точки к этому.
я не вижу различия здесь. Однако для Вашего собственного класса, который не неизменен, это поведение не важно, и необходимо вызвать конструктора.
ОБНОВЛЕНИЕ: Я был неправ! На основе вниз голосование и комментарий присоединили, я протестировал это, и поймите, что мое понимание является неправильным - новая ("Глупая") Строка действительно создает новую строку, а не снова использует существующую. Я неясен, почему это было бы (каково преимущество?), но код говорит громче, чем слова!
Я просто добавил бы, что Java имеет конструкторы Копии ...
ну, это - обычный конструктор с объектом того же типа как аргумент.
Во-первых, Вы не можете сделать класс, который расширяется от Строки, потому что Строка является заключительным классом. И Java управляет Строками по-другому по сравнению с другими классами поэтому только со Строкой, которую можно сделать
String s = "Polish";
, Но с классом необходимо вызвать конструктора. Так, тот код прекрасен.
В Java синтаксис "текст" создает экземпляр класса java.lang. Строка. Присвоение:
String foo = "text";
простое присвоение, без необходимого конструктора копии.
MyString bar = "text";
недопустимо независимо от того, что Вы делаете, потому что класс MyString не ни один java.lang. Строка или суперкласс java.lang. Строка.
CaseInsensitiveString и Строка являются различными объектами. Вы не можете сделать:
CaseInsensitiveString cis = "Polish";
, потому что "польским языком" является Строка, не CaseInsensitiveString. Если бы Строка расширила Строку CaseInsensitiveString тогда, то Вы были бы в порядке, но очевидно это не делает.
И не волнуются о конструкции здесь, Вы не будете делать ненужные объекты. При рассмотрении кода конструктора все, что он делает, хранит ссылку на строку, в которой Вы передали. Ничто дополнительное не создается.
В Строке s = новая Строка ("foobar") случай это делает что-то другое. Вы сначала создаете литеральную строку "foobar", затем создавая копию его путем построения новой строки из него. Нет никакой потребности создать ту копию.
В Вашем первом примере Вы создаете Строку, "глупую", и затем передаете его в качестве параметра конструктору копии другой Строки, который делает вторую Строку, которая идентична первому. Так как Строки Java неизменны (что-то, что часто жалит людей, которые привыкли к струнам до), это - бессмысленные траты ресурсов. Необходимо вместо этого использовать второй пример, потому что он пропускает несколько бесполезных шагов.
Однако Строковым литералом не является CaseInsensitiveString, таким образом, там Вы не можете сделать то, что Вы хотите в своем последнем примере. Кроме того, нет никакого способа перегрузиться, оператор кастинга как Вы может в C++, таким образом, нет буквально никакого способа сделать то, что Вы хотите. Необходимо вместо этого передать его в в качестве параметра конструктору класса. Конечно, я, вероятно, просто использовал бы String.toLowerCase () и был бы сделан с ним.
кроме того, Ваш CaseInsensitiveString должен реализовать интерфейс CharSequence, а также вероятно сериализуемые и Сопоставимые интерфейсы. Конечно, если Вы реализуете Сопоставимый, необходимо переопределить, равняется () и хэш-код () также.
- Как я заставляю CaseInsensitiveString вести себя как Строка, таким образом, вышеупомянутый оператор соглашается (с и w/out, расширяющий Строку)? Что о Строке делает его хорошо, чтобы просто быть в состоянии передать его литерал как этот? От моего понимания в праве Java нет никакого "понятия" конструктора копии?
Достаточно было сказано от первой точки. "Польский язык" является строковым литералом и не может быть присвоен классу CaseInsentiviveString.
Теперь о 1124-секундной точке
, Хотя Вы не можете создать новые литералы, можно следовать за первым объектом той книги для "подобного" подхода, таким образом, следующие утверждения верны:
// Lets test the insensitiveness
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;
// 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();
}
//Тест класс с помощью "утверждать" ключевого слова
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>
таким образом, создайте внутренний пул объектов CaseInsensitiveString и возвратите corrensponding экземпляр оттуда.
Этот путь "==" возвраты оператора верный для двух ссылок объектов, представляющих то же значение .
Это полезно, когда подобные объекты используются очень часто, и создание стоимости является дорогим.
документация строкового класса указывает, что класс использует внутренний пул
, класс не завершен, некоторые интересные проблемы возникает, когда мы пытаемся обойти содержание объекта при реализации интерфейса CharSequence, но этот код достаточно хорош, чтобы показать, как тот объект в Книге мог быть применен.
важно заметить, что при помощи объект internalPool, ссылки не выпущены и таким образом не предмет коллекционирования мусора, и это может стать проблемой, если много объектов создается.
Это работает на Строковый класс, потому что это используется интенсивно, и пул составлен "интернированного" объекта только.
Это работает хорошо на булев класс также, потому что существует только два возможных значения.
И наконец это - также причина, почему valueOf (интервал) в классе Целое число ограничен-128 к 127 международным значениям.
Вы не можете. Вещи в двойных кавычках в Java особенно распознаны компилятором как Строки, и к сожалению Вы не можете переопределить это (или расшириться java.lang.String
- это объявило final
).
Строки Java интересны. Похоже, что ответы ответили на некоторые интересные вопросы. Вот мои два цента.
строки неизменны (Вы никогда не можете изменять их)
String x = "x";
x = "Y";
сравнения строк зависят от того, что Вы сравниваете
String a1 = new String("A");
String a2 = new String("A");
a1
, не равняется a2
a1
, и a2
ссылки на объект я думаю, что Вы находитесь на неправильном пути с попыткой использовать нечувствительный к регистру класс. Оставьте строки в покое. То, о чем Вы действительно заботитесь, - то, как Вы отображаете или сравниваете значения. Используйте другой класс, чтобы отформатировать строку или сделать сравнения.
т.е.
TextUtility.compare(string 1, string 2)
TextUtility.compareIgnoreCase(string 1, string 2)
TextUtility.camelHump(string 1)
, Так как Вы составляете класс, можно заставить сравнивание сделать то, что Вы хотите - сравнивают текстовые значения.
String
с являются особенными в Java - они неизменны, и строковые константы автоматически превращены в String
объекты.
нет никакого пути к Вашему SomeStringClass cis = "value"
пример для применения к любому другому классу.
, И при этом Вы не можете расшириться String
, потому что это объявляется как final
, означая, что никакое разделение на подклассы не позволяется.
Строки рассматривают немного особенно в Java, они неизменны, таким образом, для них безопасно быть обработанным подсчетом ссылок.
, Если Вы пишете
String s = "Polish";
String t = "Polish";
тогда, s и t на самом деле относятся к тому же объекту, и s == t возвратит true, для "==" для чтения объектов "тот же объект" (или может, так или иначе, я "m не уверенный, если это - часть фактической спецификации языка или просто детали реализации так компилятора, возможно, не безопасно полагаться на это).
, Если Вы пишете
String s = new String("Polish");
String t = new String("Polish");
тогда s! =t (потому что Вы явно создали новую строку), хотя s.equals (t) возвратит true (потому что строка добавляет это поведение к, равняется).
вещь Вы хотите записать,
CaseInsensitiveString cis = "Polish";
не может работать, потому что Вы думаете, что цитаты являются своего рода конструктором короткого замыкания для Вашего объекта, когда на самом деле это только работает на простой java.lang. Строки.
Я полагаю, что основное преимущество использования литеральной формы (т.е., "нечто", а не новая Строка ("нечто")) - то, что все Строковые литералы 'интернируются' VM. Другими словами, это добавляется к пулу, таким образом, что любой другой код, который создает ту же строку, будет использовать объединенную Строку вместо того, чтобы создать новый экземпляр.
Для иллюстрирования следующий код распечатает верный для первой строки, но лжи для второго:
System.out.println("foo" == "foo");
System.out.println(new String("bar") == new String("bar"));
String - это один из специальных классов, в котором вы можете создавать их без новой части Sring
, это то же самое, что
int x = y;
или
char c;
То, что в вашем классе есть слово String
, не означает, что вы получаете все специальные возможности встроенного класса String
.