Статья была выбрана Github, добро пожаловать в Star:GitHub.com/Yehongqin/Лай…
Строковый класс
Частота использования класса String в Java довольно высока. Это основной класс языка Java. В пакете java.lang он в основном используется для сравнения строк, поиска, объединения и других операций. Если вы хотите глубже понять класс, лучше всего посмотреть исходный код:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
//...
}
Из исходного кода можно увидеть следующие моменты:
- Класс String изменяется с помощью ключевого слова final, указывающего, что класс String не может быть унаследован, а его методы-члены по умолчанию являются конечными методами.
- Класс String реализует интерфейсы Serializable, CharSequence и Comparable.
- Значение класса String хранится в массиве char, а массив char изменяется с помощью private и final.После того как строка создана, ее нельзя изменить.
Следующие вопросы продолжают углублять понимание класса String.
Вопрос первый
Выше говорилось, что после создания строки ее нельзя изменить.Не может ли метод replace(), предоставляемый классом String, заменить содержимое измененной строки?
На самом деле метод replace() не изменяет исходную строку, а создает новую строку для возврата, просто посмотрите на исходный код.
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;
int i = -1;
char[] val = value; /* avoid getfield opcode */
while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0; j < i; j++) {
buf[j] = val[j];
}
while (i < len) {
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
//创建一个新的字符串返回
return new String(buf, true);
}
}
return this;
}
То же самое верно и для других методов, независимо от того, выполняются ли операции sub, concat или replace над исходной строкой, но новый строковый объект создается повторно.
Вопрос второй
Зачем использовать ключевое слово final для украшения класса String?
Прежде всего, поговорим о роли финальных модифицированных классов.Класс, измененный с помощью final, не может быть унаследован, все методы-члены в классе неявно обозначаются как окончательные методы. То есть у вас не может быть подклассов, а методы-члены не могут быть переопределены.
Возвращаясь к вопросу, класс String дорабатывается в основном на основе двух соображений безопасности и эффективности.
- безопасность
Поскольку строки неизменяемы, поэтомумногопоточный безопасный, один и тот же экземпляр строки может совместно использоваться несколькими потоками. Это устраняет необходимость использования синхронизации из соображений безопасности потоков. Сами строки потокобезопасны.
String используется многими классами (библиотеками) Java в качестве параметров, таких как URL-адрес сетевого подключения, путь к файлу и параметры String, требуемые механизмом отражения, и т. д. Если String не исправлено, это вызовет различные риски безопасности.
- эффективный
Неизменяемость строк обеспечивает уникальность хеш-кодов, поэтому его можно безопасно кэшировать, что также является методом оптимизации производительности, а значит, нет необходимости каждый раз вычислять новый хэш-код.
Объединение строк возможно только в том случае, если строки неизменяемы., пул строковых констант — это специальная область хранения в куче памяти Java.При создании объекта String, если строковое значение уже существует в пуле констант, новый объект не будет создан, а будет сделана ссылка на существующий объект.
Пул строковых констант
Выделение строк, как и размещение других объектов, отнимает много времени и места, и мы часто используем строки. Чтобы повысить производительность и уменьшить нагрузку на память, JVM использует пул строковых констант для оптимизации при создании экземпляров строк.
Идея пула на самом деле не редкость в Java, и пул строковых констант аналогичная идея.При создании строки JVM сначала проверит пул строковых констант.Если строка уже существует в пуле констант, она будет вернуть константу напрямую.Ссылка на экземпляр в пуле. Если строка не существует в пуле констант, строка создается и помещается в пул констант.
Мы можем написать простой пример, чтобы доказать:
public static void main(String[] args) throws Exception {
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);//true
}
В интервью также часто задают вопрос, сколько объектов создает new String("abc")?
Это может быть проверка вашего понимания пула строковых констант, и мой общий ответ — один или два объекта.
Если строка "abc" ранее не использовалась, несомненно, создаются два объекта, один объект String создается в куче, а один создается в пуле строковых констант, всего два.
Если ранее использовалась строка "abc", объект больше не будет создаваться в пуле строковых констант, а будет получен из буфера строковых констант, а в куче будет создан только объект String.
String s1 = "abc";
String s2 = new String("abc");
//s2这行代码,只会创建一个对象
Конкатенация строк
Сращивание строк — очень распространенная операция в Java, но сращивание строк не так просто, как использование знака «+», и есть некоторые моменты, на которые следует обратить внимание, иначе это приведет к низкой эффективности.
Например следующий код:
public static void main(String[] args) throws Exception {
String s = "";
for (int i = 0; i < 10; i++) {
s+=i;
}
System.out.println(s);//0123456789
}
Что не так с использованием += для объединения строк внутри цикла? Давайте декомпилируем его и посмотрим.
На самом деле, после декомпиляции мы видим, что нижний слой класса String, использующий сплайсинг "+=", на самом деле использует StringBuilder, сначала инициализируйте объект StringBuilder, затем используйте метод append() для сращивания и, наконец, используйте метод toString() для сплайсинга. получить результат.
Проблема в том, что если вы используете объединение += в теле цикла, будет создано много временных объектов StringBuilder, и после объединения будет вызываться toString() для назначения исходному объекту String. Это создает большое количество временных объектов и может серьезно повлиять на производительность.
Поэтому при склейке строк в теле цикла рекомендуется использовать класс StringBuilder или StringBuffer, например:
public static void main(String[] args) throws Exception {
StringBuilder s = new StringBuilder();
for (int i = 0; i < 10; i++) {
s.append(i);
}
System.out.println(s.toString());//0123456789
}
Разница между StringBuilder и StringBuffer заключается в том, что все методы StringBuffer модифицируются ключевым словом sync, поэтому они потокобезопасны, а StringBuilder небезопасен для потоков (высокоэффективен).
Суммировать
Для обзора в этой статье представлены неизменяемые характеристики класса String, а также роль пула строковых констант и, наконец, выдвинуты некоторые предложения по сращиванию строк на уровне компиляции JVM. Так называемый просмотр старого и изучение нового, даже некоторые очень простые и распространенные классы, если вы изучите их глубже, будут некоторые выгоды.
Это все, что касается этой статьи, спасибо за чтение, я надеюсь, что вы сможете что-то получить после ее прочтения!
Статьи постоянно обновляются. Wechat ищет «энтузиастов технологии Java», а отправленные технические статьи получают как можно скорее после того, как обращают на них внимание. Статьи классифицируются и включаются в github:github.com/yehongzhi, вы всегда сможете найти то, что вас интересует
Ставьте лайки, если считаете это полезным, ваши лайки — самая большая мотивация для моего творчества.~
Я программист, который изо всех сил старается запомниться. Увидимся в следующий раз! ! !
Возможности ограничены, если есть какие-то ошибки или неуместности, просьба критиковать и исправлять их, учиться и обмениваться вместе!