Метод codePointAt() в Java

Есть ли разница в использовании методов

static int codePointAt(CharSequence seq, int index)

из класса Character и

int codePointAt(int index)

из класса String (кроме того, что в первом используется CharSequence)? Результат возвращают вроде бы один и тот же.


Ответы (1 шт):

Автор решения: Nowhere Man

Данные методы незначительно отличаются реализацией при доступе к символам.

Пример (для Open JDK 8):

public static int codePointAt(CharSequence seq, int index) {
    char c1 = seq.charAt(index);
    if (isHighSurrogate(c1) && ++index < seq.length()) {
        char c2 = seq.charAt(index);
        if (isLowSurrogate(c2)) {
            return toCodePoint(c1, c2);
        }
    }
    return c1;
}

Соответственно, для строки реализация метода String::charAt сводится к проверке индекса и прямому доступу через внутренний массив символов char[] value:

// String::charAt
public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}
  • String::codePointAt:
    Фактически он просто проверяет индекс, чтобы выбросить особое исключение StringIndexOutOfBoundsException при выходе за пределы строки и вызывает статический метод Character.codePointAtImpl (доступный по умолчанию только в пакете java.lang), передавая в него ссылку на внутренний массив символов данной строки:
public int codePointAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return Character.codePointAtImpl(value, index, value.length);
}

Аналогично, реализация метода Character.codePointAtImpl напрямую обращается по индексу к элементам массива:

static int codePointAtImpl(char[] a, int index, int limit) {
    char c1 = a[index];
    if (isHighSurrogate(c1) && ++index < limit) {
        char c2 = a[index];
        if (isLowSurrogate(c2)) {
            return toCodePoint(c1, c2);
        }
    }
    return c1;
}

То есть, вызов метода String::codePointAt несколько эффективнее, так как позволяет избежать двойной проверки выхода за пределы массива символов, которая происходит при двойном вызове метода String::charAt.

→ Ссылка