Замечательные Java строки

Нюансы — это такая замечательная вещь, однако они часто остаются незамеченными.

Блуждая в пространстве спецификации языка java иногда встречаешь интригующие откровения, помнить о которых хотелось бы постоянно, чтобы не ломать голову над вдруг подвернувшимся "багом".

На первый взгляд почти элементарный объект — строка, несёт с собой довольно обширный пласт необходимых знаний, без которых можно периодически присаживаться в лужу.

В тексте программы часто встречаются литералы строк — это наборы символов заключенных в двойные кавычки ("Строка"). Причём, символы их составляющие, кодируются в UTF-16. Литералы символов записываются в апострофах ('A'). Символы вводятся напрямую с клавиатуры, либо с помощью эскейп последовательностей. Которые, в свою очередь записываются либо с помощью шестнадцатеричного кода, например \u0041 (большая латинская A), либо с помощью управляющих символов, например \n (разрыв строки).

Символы UTF-16 двухбайтовые, это отражено в простом типе char, однако нужно учесть что в данной кодировке есть символы которых немного "зашкаливает". Поэтому, например, записать их в строчном литерале удастся, а вот с символьным литералом возникнут проблемы. Это суррогатные символы, им требуется уже четыре байта. Конечно хватило бы и трёх, но специальные алгоритмы представления, да и необходимость записывать их затем строкой, дают нам четырехбайтный суррогатный символ. Примером их могут быть символы музыкальной грамоты: скрипичный ключ, символ ноты.

\uD834\uDD1E — sk
\uD834\uDD5E — n

Вы можете попробовать вывести эти символы в консоль с помощью обычного:

System.out.println("\uD834\uDD1E");

Однако, если ваша консоль не поддерживает UTF-16 то вы не увидите соответствующих символов (в Windows у меня не получилось вывести символы, в Ubuntu получилось).

Любая строка, появляющаяся в тексте программы, или по ходу работы программы, это почти всегда новый объект в памяти. Они так и называются — неизменяемые объекты. Единственная доступная для строк операция сложения, не изменяет имеющуюся строку а создаёт новую, заменяя старую ссылку на новую.

String s = "first";
s = s + "second";

Как может показаться, джава расточительна в строках. Однако это не совсем так.

Для строк существует контейнер (пул), в который помещаются неповторимые строковые значения, а затем в программе используются ссылки на них. Слежение за строками происходит как на этапе компиляции так и исполнения программы, поэтому дублирования строк можно избежать. Для проверки этого свойства джава машины, воспользуемся операцией сравнения на равенство == ссылок на строки.

String s1 = "Hello";
String s2 = "He" + "llo";
System.out.println(s1 == s2); //должна вывести true
String s3 = "llo";
s3 = "He" + s3;
System.out.println(s1 == s3); //должна вывести false
s3 = s3.intern();
System.out.println(s1 == s3); //должна вывести true

Обратите внимание на первые две переменные s1 и s2, их значение может быть вычислено на этапе компиляции, поэтому один экземпляр строки попадает в пул строк, а переменным присваивается одна и та же ссылка. Если компилятор бессилен, то на этапе исполнения будет создан новый объект с похожим значением — переменная s3. Однако и это можно регулировать, с помощью метода текущего объекта строки intern(). Он занимается поиском подходящей строки в пуле и возвратом ссылки на неё. Таким образом можно экономить память программы.

Понравилась статья? Посоветуйте другу

Количество коментариев: 0

Добавить комментарий



[ Ctrl + Enter ]