Якщо String - клас, як і будь-який інший, то як його можна ініціалізувати, використовуючи подвійні лапки?
java.lang.String
мати спеціальну обробку мови Java.
Якщо String - клас, як і будь-який інший, то як його можна ініціалізувати, використовуючи подвійні лапки?
java.lang.String
мати спеціальну обробку мови Java.
Відповіді:
Дизайнери Java вирішили зберегти примітивні типи в об'єктно-орієнтованій мові, а не робити все об'єктом, щоб покращити продуктивність мови. Примітиви зберігаються в стеку викликів, де потрібно менше місця для зберігання і дешевше маніпулювати. З іншого боку, в купі програм зберігаються об'єкти, для яких потрібне складне управління пам’яттю та більше місця для зберігання.
З причини продуктивності Java String створений таким чином, щоб він знаходився між примітивом і класом.
Наприклад
String s1 = "Hello"; // String literal
String s2 = "Hello"; // String literal
String s3 = s1; // same reference
String s4 = new String("Hello"); // String object
String s5 = new String("Hello"); // String object
Примітка: Строкові літерали зберігаються в загальному пулі. Це полегшує обмін пам’яті для рядків з однаковим вмістом для збереження пам’яті. String
Об'єкти, виділені за допомогою нового оператора, зберігаються у сховищі heap
та немає спільного зберігання для того самого вмісту.
Java трактує String як особливий клас, його можна ініціалізувати обома способами
Безпосередньо присвоєння буквального
String a = "adsasdf";
Як і інші об'єкти, що використовують нове ключове слово
String a = new String("adsasdf");
Вам потрібно бути особливо обережним, коли ви хочете порівняти зі ==
знаком:
String a = "asdf";
String b = "asdf";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // True
String a = new String("asdf");
String b = new String("asdf");
System.out.println(a == b); // False
System.out.println(a.equals(b)); // True
Це тому, що в першому випадку об'єкти a і b зберігаються у чомусь, що називається, literal pool
і вони обидва посилаються на один і той же об'єкт, тому вони є рівними в обох напрямках.
Але у другому випадку a і b посилаються на різні об'єкти, наприклад, коли ми ініціалізуємо будь-які інші об'єкти. тому вони нерівні порівняно з ==
оператором, тоді як вони рівні за значеннями.
String отримує особливу обробку в JLS: це один із двох непомітивних типів, для яких існують літерали (інший - *Class
) * .
Від JLS :
Строковий буквал - це посилання на екземпляр класу `String [...].
* ну, також є "нульовий тип" з його "нульовим буквальним" null
, але більшість людей не вважають "нульовий тип" належним типом.
null
призначити будь-яку змінну опорного типу. Інакше це не цікавий тип.
Текст всередині подвійних лапок створює буквальний String
об’єкт.
String myString = "Some text";
Код вище створює String
об'єкт, використовуючи подвійні лапки.
Струни дуже часто використовуються в мові програмування. Оскільки java є об'єктно-орієнтованою, рядок є об'єктом. Щоб уникнути громіздкої нової струни ("someString"); оператор щоразу, коли вам потрібен об'єкт рядка, Java дозволяє вам просто створити об'єкт рядка, використовуючи літеральний рядок.
Але слід пам’ятати про рівність рядків. Ось короткий тест JUnit, щоб продемонструвати, що я маю на увазі.
@Test
public void stringTest() {
// a string literal and a string object created
// with the same literal are equal
assertEquals("string", new String("string"));
// two string literals are the same string object
assertSame("string", "string");
// a string literal is not the same object instance
// as a string object created with the same string literal
assertFalse("string" == new String("string"));
// java's String.intern() method gives you the same
// string object reference for all strings that are equal.
assertSame("string", new String("string").intern());
}
new String(String src)
, тоді ви навіть не змогли б надати конструктору рядковий буквал. Вам потрібно було б ініціалізувати a char []
, а потім використати пристрій String(char [] src)
для конструювання рядка, або вам доведеться прочитати рядок з файлу.
- String - це клас на Java . Ви маєте рацію з цим, тому ми завжди можемо ініціалізувати new
ключове слово.
- Але коли ми робимо щось на кшталт:
String s = "";
Вищенаведене твердження позначено компілятором як спеціальний об'єкт String, а потім JVM під час завантаження класу (завантаження робиться перед ініціалізацією), бачить це те, що відомо як строковий літерал , який зберігається в пулу літеральних рядків .
- Отже, String можна створити за допомогою new()
та ""
методом, але останній надає рядковий літерал, який залишається в купі, навіть коли немає посилання на цей об'єкт рядка, оскільки він має посилання з пулу літеральних рядків.
Java виконує двоетапний процес для нас.
String str = "hello";
еквівалентно
char data[] = {'h', 'e', 'l' , 'l', 'o'};
String str = new String(data);
Як і. .NET] [1] отримав подібну річ.
String(Char[]) constructor
робить
String(char[] value)
Додавання посилань: -
"hello"
це рядковий літерал і компілятор буде поставлений у постійний пул, див. JLS §3.10.5 та JVMS §5.1 .
Java.lang.String
це не просто клас. Це невід'ємна частина основної мови. У компіляторі є синтаксичний цукор для нього. Наприклад, ""
це як абревіатура для new String("")
. Під час написання ""
компілятор оптимізує однакові рядки до одного і того ж екземпляра, щоб заощадити місце."a" + 5 == "a5" ==> true
У компіляторі є синтаксичний цукор для багатьох речей, у тому числі не потрібно встановлювати / розкривати ящик між об’єктними версіями та їх рідними типами, немає батьківських засобів Об'єкт, конструктор за замовчуванням, ...
""
не є абревіатурою для new String("")
. Якщо ви користуєтесь ""
, перше, що буде зроблено, це шукати відповідники в басейні String JVM, і якщо це правда, вона поверне цю String. Використовуючи new String("")
, ви завжди створюватимете нову String, навіть якщо сама String вже існує в пулі String (оскільки вона не буде зберігатися в пулі String).
" "
це вже Рядок!