Предисловие
Эта статья в основном представляет соответствующий контент об анализе исходного кода JDK, StringBuilder и StringBuffer. Это обменивается вашей ссылкой и обучением. Я не скажу многое ниже. Давайте посмотрим на подробное введение вместе.
Заявление класса строки
Публичный окончательный класс Строка реализует java.io.serializable, сопоставимый <string>, charequence {…}Класс строки использует окончательный модификатор, чтобы указать, что его нельзя унаследовать. В то же время он также реализует три интерфейса, реализуя сериализуемый интерфейс, чтобы указать, что класс строки может быть сериализован; Реализация сопоставимого интерфейса <T> в основном обеспечивает метод сравнения для сравнения строковых строк; Также реализует интерфейс Char -Sevectence, который представляет, что CHAR стоит читаемой последовательности (Charbuffer, Segment, String, StringBuffer и StringBuilder также реализует интерфейс ChareSequence)
Строковые основные поля и описания атрибутов
/*Значение массива символов, хранение фактических символов в строке*/частное окончательное значение CHAR [];/*Значение хеш -значения строки по умолчанию 0*/private int hash; /*Значение хеш -значения строки по умолчанию 0*//*Кораптор, используемый для сортировки объектов строки, метод сравнения, используется*/public static final Comparator <string> case_insensitive_dord = new caseinsensitivecomparator ();
Анализ частичного метода строки
Класс строки предоставляет ряд конструкторов, и некоторые из них больше не рекомендуются, как показано на рисунке ниже:
Конструктор
Вот реализации двух часто используемых конструкторов:
// string str = new String ("123") public String (string riginal) {this.value = original.value; this.hash = riginal.hash;} // string str3 = new String (new char [] {'1', '2', '3'}); public String (char value []) {// Копировать значение массива символов, чтобы значение this.value = arrays.copyof (value.length); }Boolean Equals (объект anobject)
Класс строки переопределяет метод Equals, чтобы сравнить эту строку с указанным объектом. Результат верен, если и только тогда, когда параметр не является нулевым и является строковым объектом, представляющим ту же последовательность символов, что и этот объект.
public boolean equals (object anobject) {// сравнить ссылки на объект напрямую и вернуть true if (this == anobject) {return true; } // Сравните последовательность символов текущего объекта со значением anobject if (anobject string string) {string anotherstring = (string) anobject; int n = value.length; if (n == anotherstring.value.length) {char v1 [] = value; char v2 [] = anotherstring.value; int i = 0; while (n--! = 0) {if (v1 [i]! = v2 [i]) вернуть false; i ++; } вернуть true; }} вернуть false; }int сравнивать (String Anotherstring)
Сравните последовательность символов двух строк бит. Если немного символа не совпадает, верните разницу в значении Unicode в двух символах этого бита. Все биты одинаковы, рассчитайте разницу по длине двух строк. Если две строки одинаковы, верните 0.
public int compareto (String anotherstring) {int len1 = value.length; int len2 = anotherstring.value.length; // взять длину строки с меньшей длиной int lim = math.min (len1, len2); char v1 [] = value; char v2 [] = anotherstring.value; int k = 0; В то время как (k <lim) {// сравнить значение символов двух строк один за другим. Если это не равное, верните разницу между Unicode двух символов в этой позиции char c1 = v1 [k]; char c2 = v2 [k]; if (c1! = c2) {return c1 - c2; // возвращать разницу между Unicode} k ++; } // Все биты меньшей строки сравниваются, а разница между длиной двух строк возвращается // Если две строки одинаковы, разница между длиной составляет 0, то есть та же строка возвращает 0 return len1 - len2; } Метод CompareToIgnoreCase (String Str) реализован аналогичным образом. Верхний и нижний случай символов игнорируется во время сравнения, а метод реализации выглядит следующим образом:
public int compare (String S1, String S2) {int n1 = s1.length (); int n2 = s2.length (); int min = math.min (n1, n2); for (int i = 0; i <min; i ++) {char c1 = s1.charat (i); char c2 = s2.charat (i); if (c1! = c2) {c1 = символ.touppercase (c1); c2 = символ.touppercase (C2); if (c1! = c2) {c1 = символ.tolowercase (c1); c2 = символ. if (c1! = c2) {// no overflow из -за численного повышения возврата C1 - C2; }}}} return n1 - n2; }Native String Intern ()
Когда вызывается метод стажировки, если пул уже содержит строку, равную этому строковому объекту (определяется с помощью метода equals (объект)), возвращается строка в пуле. В противном случае добавьте этот объект строки в пул и верните ссылку на этот объект строки.
Все буквальные строки и строковые постоянные выражения управляются с использованием метода стажера, например: String str1 = "123";
Местоположение строковой памяти: постоянный бассейн или куча
Строковые объекты могут создаваться непосредственно через литералы или через конструкторы. В чем разница?
1. Строковые объекты, созданные буквальными или буквальными струнами через «+», хранятся в постоянном пуле. Если постоянный пул существует во время фактического создания, ссылка будет возвращена непосредственно. Если его не существует, строковый объект будет создан.
2. Создайте строковый объект с использованием конструктора и создайте строковый объект непосредственно в куче
3. Вызовите метод стажера, и вернуть объект будет помещен в постоянный пул (если его не существует, он будет помещен в постоянный пул, и если он существует, он будет возвращен в ссылку)
Ниже приведен пример распределения памяти объектов String:
String str1 = new String ("123"); String str2 = "123"; String str3 = "123"; String str4 = str1.intern (); System.out.println (str1 == str2); // false Str1 создает объект в куче, Str2 создает объект в системе постоянного пула.out.println (str2 == str3); // True Str2 создает объект в постоянном пуле, STR3 непосредственно возвращает ссылку на объект, созданный STR2, поэтому STR2 и STR3 указывают на тот же объект в системе постоянного пула.out.println (str4 == str3); // True Str4 возвращает объект со значением «123» в постоянном пуле, поэтому STR4, STR2 и Str3 равны.О примере строки пример:
открытый класс StringTest {public Static Final String x = "ABC"; // постоянная x @test public void test () {string str5 = new String ("abc"); String str6 = str5+"def"; // Создать строку str7 = "abc"+"def"; // постоянная строка пула str8 = x+"def"; // x является постоянной, а значение фиксируется, поэтому значение x+"def" было установлено в ABCDEF. Фактически, после компиляции код эквивалентен string str8 = "abcdef" string str9 = "abc"; String str10 = str9+"def"; //System.out.println(str6==str7); // false System.out.println (str8 == str7); // true System.out.println (str10 == str7); // false System.out.println (x == str9); //истинный} }Декомпилированный код будет ясно с первого взгляда:
Распределение памяти следующее:
String, StringBuffer, StringBuilder
Поскольку массив символов значения свойства [] для хранения строк, поддерживаемого внутри строки, изменяется с помощью окончательного:
/** Значение используется для хранения символов. */Частное окончательное значение char [];
Это указывает на то, что его можно изменить после назначения. Поэтому мы считаем, что строковый объект неизменен после создания. Если вы сталкиваетесь с частыми операциями сплайсинговой строки во время разработки, если вы используете контакт, предоставляемый строкой, или напрямую используете строку сплайсинга «+», будут часто генерируются новые строки, что будет неэффективно. Java предоставляет два других класса: StringBuffer и StringBuilder, которые используются для решения этой проблемы:
Посмотрите на следующий код:
String str1 = "123"; String str2 = "456"; String str3 = "789"; String Str4 = "123" + "456" + "789"; // Добавить константы, компилятор автоматически распознает строку str4 = "123456789" String Str5 = str1 + str2 + str3; // Сплюсная сплайсинг String Variable, рекомендуется использовать StringBuilder StringBuilder SB = new StringBuilder (); SB.Append (Str1); SB.Append (Str2); SB.Append (Str3);
Ниже приводится реализация класса StringBuilder, который перехватывает только некоторые из анализируемых кода:
public Final Class StringBuilder расширяет AbstractStringBuilder, реализует java.io.serializable, char -sequence {// split string @Override publicbuilder Append (String Str) {// Вызов родительского класса AbstractStringBuilder.Append Super.Append (str); вернуть это; }} Abstract Class AbstractStringBuilder реализует добавление, ChareSequence { / *** Массив символов, который хранит строки, нефинальный тип, отличается от класса строки* / char [] значение; /*** Подсчет - это количество используемых символов. */ int count; public AbstractStringBuilder Append (String Str) {if (str == null) return appendnull (); int len = str.length (); // Проверьте, должна ли емкость быть расширена до EncureCapacityInternal (COUNT + LEN); // Скопировать строку str в значение str.getchars (0, len, value, count); count += len; вернуть это;} private void EnsureCapacityInternal (int minimumCapacity) {// код из переполнения // mimimumCapacity = count+str.length // Если емкость после STR сплайсированной, больше, чем емкость значения, Expand if (Минимум -энтузиазм - значение. lowletry> 0) {// Расширение емко Arrays.copyof (значение, newcapacity (Minimumcapacity)); }} // stringBuilder Расширение Private int newCapacity (int mincapacity) {// Код с переполнением // Рассчитайте емкость расширения // Длина массива расширения по умолчанию расширяется на 2 раза больше исходного числа (значение []) Длина группы, а затем 2 добавляются в правило. Зачем добавлять 2? int newcapacity = (value.length << 1) + 2; if (newcapacity - mincapacity <0) {newcapacity = mincapacity; } return (newCapacity <= 0 || max_array_size - newcapacity <0)? Hugecapacity (Mincapacity): Newcapacity; }}То же самое относится и к StringBuffer и StringBuilder. Значение [] массив символов, поддерживаемая внутри, является изменчивым. Единственное отличие состоит в том, что StringBuffer безопасен для потока. Он синхронизирует все методы. StringBuilder-это нить не безопасно. Следовательно, при многопоточной эксплуатации и обмене строковыми переменными, StringBuffer предпочтительнее для обработки сплайсинга строк. В противном случае можно использовать StringBuilder. В конце концов, синхронизация потоков также принесет определенное потребление.
Суммировать
Вышеуказанное - все содержание этой статьи. Я надеюсь, что содержание этой статьи имеет определенную справочную ценность для каждого обучения или работы. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения. Спасибо за поддержку Wulin.com.