предисловие
верить какJAVAER
, наиболее часто используемый в кодировании должен бытьString
строку, и я считаю, что должно быть много людей дляString
изapi
Я знаком с ним, но реализации его исходного кода не видел.На самом деле, я лично считаю, что для использования api первым этапом является просмотр его официальной документации.По мере накопления опыта разработки вы следует попытаться взглянуть на реализацию исходного кода, что очень важно для ваших собственных способностей, улучшение имеет решающее значение.После того, как вы поймете исходный код, вам будет удобнее использовать API!
Примечание: Следующие записи основаны наjdk8окрестности
Строка - это просто класс
String
На самом деле это просто класс, мы можем грубо проанализировать его со следующих сторон:
- наследование классов
- переменная-член класса
- конструктор класса
- метод члена класса
- Связанные статические методы
отношения наследования
отIDEA
Автономный плагин экспортаString
Диаграмма классов UML выглядит следующим образом:
Как видно сразу из рисунка,String
реализует интерфейсSerializable
,Comparable
,CharSequence
, кратко представим роль этих трех интерфейсов:
-
Serializable
: класс, который реализует этот интерфейс, будет иметь возможность сериализации.У этого интерфейса нет никакой реализации, он используется только для идентификации. -
Comparable
: классы, реализующие этот интерфейс, имеют возможность сравнивать размеры. Например, список (и массив) объектов, реализующих этот интерфейс, может быть определен какCollections
статический метод классаsort
для автоматической сортировки. -
CharSequence
: I интерфейс для единообразия последовательности символов. Предоставляет общие методы манипулирования последовательностями символов, обычно некоторыетолько чтениеметод, многие классы, связанные с символами, реализуют этот интерфейс для работы с последовательностями символов, например:String
,StringBuffer
Ждать.
String
Класс определяется следующим образом:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence{
...
}
Зависит отfinal
модификаторы известны,String
Классы — это ненаследуемые, неизменяемые классы.
переменная-член класса
Здесь мы в основном вводим одну из наиболее важных переменных-членовvalue[]
, который определяется следующим образом:
/** The value is used for character storage. */
private final char value[];
String
это строка, состоящая из символовchar
состоит из, так что на самом делеString
Внутри на самом деле массив символов, сvalue[]
Выражать,Обратите внимание, что значение [] здесь изменено с помощью final, что указывает на то, что значение не может быть изменено..
конструктор класса
String
Существует множество перегруженных конструкторов, которые описываются следующим образом:
- Метод построения пустого параметра, инициализируйте экземпляр строки, по умолчанию используется пустой символ, теоретически не нужно использовать этот метод построения, фактически определите пустой символ
String = ""
инициализирует пустую строкуString
объект, и этот конструктор также обрабатывает нулевой символvalue[]
Просто скопируйте его один раз, исходный код реализован следующим образом:public String() { this.value = "".value; }
- Создан со строковым аргументом
String
объект, который фактически будет параметромvalue
а такжеhash
Присвоение объекту экземпляра в качестве инициализации эквивалентно глубокому копированию формального параметра.String
объект, исходный код выглядит следующим образом:public String(String original) { this.value = original.value; this.hash = original.hash; }
- построить новый из массива символов
String
объект, используемый здесьArrays.copyOf
метод копирования массива символовpublic String(char value[]) { this.value = Arrays.copyOf(value, value.length); }
- На основе исходного массива символов через смещение (начальную позицию) и количество символов перехватить и построить новый
String
объект.public String(char value[], int offset, int count) { //如果偏移量小于0,则抛出越界异常 if (offset < 0) { throw new StringIndexOutOfBoundsException(offset); } if (count <= 0) { //如果字符数量小于0,则抛出越界异常 if (count < 0) { throw new StringIndexOutOfBoundsException(count); } //在截取的字符数量为0的情况下,偏移量在字符串长度范围内,则返回空字符 if (offset <= value.length) { this.value = "".value; return; } } // Note: offset or count might be near -1>>>1. //如果偏移量大于字符总长度-截取的字符长度,则抛出越界异常 if (offset > value.length - count) { throw new StringIndexOutOfBoundsException(offset + count); } //使用Arrays.copyOfRange静态方法,截取一定范围的字符数组,从offset开始,长度为offset+count,赋值给当前实例的字符数组 this.value = Arrays.copyOfRange(value, offset, offset+count); }
- На основе исходного целочисленного массива по смещению (начальной позиции) и количеству символов перехватить и построить новый
String
объект. Представление целочисленного массива здесьЦелочисленное значение ASCII, соответствующее символуpublic String(int[] codePoints, int offset, int count) { //如果偏移量小于0,则抛出越界异常 if (offset < 0) { throw new StringIndexOutOfBoundsException(offset); } if (count <= 0) { //如果字符数量小于0,则抛出越界异常 if (count < 0) { throw new StringIndexOutOfBoundsException(count); } //在截取的字符数量为0的情况下,偏移量在字符串长度范围内,则返回空字符 if (offset <= codePoints.length) { this.value = "".value; return; } } // Note: offset or count might be near -1>>>1. 如果偏移量大于字符总长度-截取的字符长度,则抛出越界异常 //if (offset > codePoints.length - count) { throw new StringIndexOutOfBoundsException(offset + count); } final int end = offset + count; // 这段逻辑是计算出字符数组的精确大小n,过滤掉一些不合法的int数据 int n = count; for (int i = offset; i < end; i++) { int c = codePoints[i]; if (Character.isBmpCodePoint(c)) continue; else if (Character.isValidCodePoint(c)) n++; else throw new IllegalArgumentException(Integer.toString(c)); } // 按照上一步骤计算出来的数组大小初始化数组 final char[] v = new char[n]; //遍历填充字符数组 for (int i = offset, j = 0; i < end; i++, j++) { int c = codePoints[i]; if (Character.isBmpCodePoint(c)) v[j] = (char)c; else Character.toSurrogates(c, v, j++); } //赋值给当前实例的字符数组 this.value = v; }
- Через исходный байтовый массив, по определенному диапазону, перехватываем длины длин от смещения, и инициализируем
String
instance, и кодировку символов можно указать одновременно.public String(byte bytes[], int offset, int length, String charsetName) throws UnsupportedEncodingException { //字符编码参数为空,抛出空指针异常 if (charsetName == null) throw new NullPointerException("charsetName"); //静态方法 检查字节数组的索引是否越界 checkBounds(bytes, offset, length); //使用 StringCoding.decode 将字节数组按照一定范围解码为字符串,从offset开始截取length个长度 this.value = StringCoding.decode(charsetName, bytes, offset, length); }
- Аналогичен 6-й конструкции, за исключением того, что параметр кодирования перегружен как
Charset
Типыpublic String(byte bytes[], int offset, int length, Charset charset) { if (charset == null) throw new NullPointerException("charset"); checkBounds(bytes, offset, length); this.value = StringCoding.decode(charset, bytes, offset, length); }
- Создайте экземпляр строки с помощью исходного массива байтов и укажите кодировку символов. Конкретная реализация на самом деле состоит в том, чтобы вызвать шестой конструктор, начальная позиция равна 0, а длина перехвата - это длина массива байтов.
public String(byte bytes[], String charsetName) throws UnsupportedEncodingException { this(bytes, 0, bytes.length, charsetName); }
- Создайте экземпляр строки с помощью исходного массива байтов и укажите кодировку символов. Конкретная реализация на самом деле заключается в вызове седьмого конструктора, начальная позиция равна 0, а длина перехвата — это длина массива байтов.
public String(byte bytes[], Charset charset) { this(bytes, 0, bytes.length, charset); }
- Через исходный байтовый массив, по определенному диапазону, перехватываем длины длин от смещения, и инициализируем
String
Экземпляр, в отличие от шестого конструктора, использует системную кодировку символов по умолчанию.public String(byte bytes[], int offset, int length) { //检查索引是否越界 checkBounds(bytes, offset, length); //使用系统默认字符编码解码字节数组为字符数组 this.value = StringCoding.decode(bytes, offset, length); }
- Создайте экземпляр строки с помощью исходного массива байтов и используйте кодировку системы по умолчанию. Конкретная реализация на самом деле состоит в том, чтобы вызвать 10-й конструктор, начальная позиция равна 0, а длина перехвата - это длина массива байтов.
public String(byte bytes[]) { this(bytes, 0, bytes.length); }
- будет
StringBuffer
построить в новомString
, что является более особенным, так это то, что этот метод имеетsynchronized
Блокировки позволяют только одному потоку получить доступ к этому за разbuffer
встроить вString
объект, который является потокобезопаснымpublic String(StringBuffer buffer) { //对当前 StringBuffer 对象加同步锁 synchronized(buffer) { //拷贝 StringBuffer 字符数组给当前实例的字符数组 this.value = Arrays.copyOf(buffer.getValue(), buffer.length()); } }
- будет
StringBuilder
построить в новомString
, в отличие от 12-го конструктора, этот конструктор не является потокобезопаснымpublic String(StringBuilder builder) { this.value = Arrays.copyOf(builder.getValue(), builder.length()); }
метод члена класса
-
Получить длину строки, фактически получить длину массива символов
public int length() { return value.length; }
-
Судить о том, пуста ли строка, на самом деле означает, равна ли длина сложного массива символов 0
public boolean isEmpty() { return value.length == 0; }
-
Получить символ на основе параметра индекса
public char charAt(int index) { //索引小于0或者索引大于字符数组长度,则抛出越界异常 if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } //返回字符数组指定位置字符 return value[index]; }
-
Получить код ASIC указанного символа (тип int) в соответствии с параметром index
public int codePointAt(int index) { //索引小于0或者索引大于字符数组长度,则抛出越界异 if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } //返回索引位置指定字符ASSIC码(int类型) return Character.codePointAtImpl(value, index, value.length); }
-
Возвращает код ASIC (тип int) предыдущего элемента элемента в позиции индекса
public int codePointBefore(int index) { //获得index前一个元素的索引位置 int i = index - 1; //检查索引是否越界 if ((i < 0) || (i >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return Character.codePointBeforeImpl(value, index, 0); }
-
Метод возвращает количество кодовых точек, которое является фактическим количеством символов.Функция похожа на length().Для обычного String нет разницы между методом длины и codePointCount, которые оба возвращают количество символов. Но есть разница, когда String имеет тип Unicode. Например: String str = "/uD835/uDD6B" (даже 'Z'), length() = 2, codePointCount() = 1
public int codePointCount(int beginIndex, int endIndex) { if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) { throw new IndexOutOfBoundsException(); } return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex); }
-
Это также относится к набору символов Unicode. От позиции индекса сместите позиции codePointOffset и верните позицию смещения. Например, index = 2, codePointOffset = 3, возможно, верните 5
public int offsetByCodePoints(int index, int codePointOffset) { if (index < 0 || index > value.length) { throw new IndexOutOfBoundsException(); } return Character.offsetByCodePointsImpl(value, 0, value.length, index, codePointOffset); }
-
Это не внешний метод, который вызывается внутри String, потому что он не имеет модификатора доступа и разрешает доступ к параметрам только классам в том же пакете: dst[] — целевой массив, dstBegin — смещение целевого массива. , Чтобы скопировать прошлую начальную позицию (перезаписать откуда в целевом массиве), функция состоит в том, чтобы скопировать все значение массива символов String в массив символов dst и начать копирование с позиции dstBegin массива dst.
void getChars(char dst[], int dstBegin) { System.arraycopy(value, 0, dst, dstBegin, value.length); }
-
Чтобы получить массив символов char, принцип заключается в том, что метод getChars() копирует символы строки в целевой массив символов. Параметры: srcBegin — начальная позиция исходной строки, srcEnd — позиция после конца копируемого символа в исходной строке (то есть область копирования не включает srcEnd) dst[] — целевой массив символов, dstBegin — это смещение копии целевого количества символов, скопированные символы перезаписываются, начиная с позиции dstBegin целевого массива символов.
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); } if (srcEnd > value.length) { throw new StringIndexOutOfBoundsException(srcEnd); } if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); } System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); }
-
Получите массив байтов строки и декодируйте строку в массив байтов в соответствии с указанной кодировкой символов.
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException { if (charsetName == null) throw new NullPointerException(); return StringCoding.encode(charsetName, value, 0, value.length); }
-
Получите массив байтов строки и декодируйте строку в массив байтов в соответствии с указанной кодировкой символов.
public byte[] getBytes(Charset charset) { if (charset == null) throw new NullPointerException(); return StringCoding.encode(charset, value, 0, value.length); }
-
Получите массив байтов строки и декодируйте строку в массив байтов в соответствии с системной кодировкой символов по умолчанию.
public byte[] getBytes() { return StringCoding.encode(value, 0, value.length); }
простое резюме
-
String
Измененоfinal
Модифицированный, не может быть унаследован, неизменяемый класс -
String
выполнитьSerializable
интерфейс, который можно сериализовать -
String
выполнитьComparable
интерфейс, который можно использовать для сравнения размеров -
String
выполнитьCharSequence
Интерфейс, представляющий всегда упорядоченную последовательность символов, реализующий общий метод последовательности символов. -
String
Является последовательностью символов, внутренняя структура данных фактически является массивом символов, и все методы операций являются операциями вокруг этого массива символов. -
String
часто используется вSystem
Категорияarraycopy
метод, целью которого является копирование массива символов
В конце концов
По космическим причинам,String
Первое резюме находится здесь первым, а последующая часть напишет еще одну запись. Она будет опубликована в общедоступном аккаунте [Чжан Шаолинь] как можно скорее. Добро пожаловать, обратите внимание!