JDK源码阅读-CharSequence接口

2,095 阅读3分钟

概述

java.lang.CharSequence接口是一个可读的字符序列。此接口为不同类型的字符序列提供了一种统一且只读的访问方式。如String、StringBuilder、CharArray等都实现了该接口。
CharSequence接口没refine Object类中定义的equals和hashCode方法的通用约定,因此对于两个实现了该接口的对象而言,在进行对比是,通常其结果也是未定义的。同时,使用任意的CharSequence实例作为set集合的元素或者map中的key是不合适的,因为实现该接口的每个对象可以由不同的类来实现,导致无法保证每个类都有和其他类实例有等价的测试能力。

声明方式

java不可以直接new一个抽象类型或者接口的对象,但是可以直接为其赋予合法的值,如:CharSequence cs = "charSequence";

方法

CharSequence接口方法
从上图,我们可以看到经常在字符串中使用的length(),charAt(int)等方法。

length()方法

返回字符序列的长度。由于String类采用的是UTF-16编码,因此该方法返回的值肯定是16bit的整数倍。

int length(); // 接口的方法默认由public修饰

charAt(int)方法

  • 返回指定索引index位置处的字符。
  • 如果指定索引位置处的字符值为surrogate字符,则返回这个surrogate字符。(surrogate的出现原因:因为UTF-16采用2个字节存储一个字符,但是有的字符存储只需要一个字节,比如英文字符,那么下一个字节也不能继续存储其他的字符,而只能存储一个代表字符,来占用这一个字节的位置,接下来的一个字节处才能继续存储下一个字符)。
char charAt(int index);

subSequence(int, int)方法

返回一个由原字符序列截取的子序列。子序列包含原序列的第start个位置的字符,但不含第end个位置的字符。另外,如果入参start==end,则返回空序列。

CharSequence subSequence(int start, int end);

toString()方法

染回字符序列的字符串形式。

public String toString();

chars()方法

这个方法是在jdk1.8新加的,先占个坑,之后再分析。

    public default IntStream chars() {
        class CharIterator implements PrimitiveIterator.OfInt {
            int cur = 0;

            public boolean hasNext() {
                return cur < length();
            }

            public int nextInt() {
                if (hasNext()) {
                    return charAt(cur++);
                } else {
                    throw new NoSuchElementException();
                }
            }

            @Override
            public void forEachRemaining(IntConsumer block) {
                for (; cur < length(); cur++) {
                    block.accept(charAt(cur));
                }
            }
        }

        return StreamSupport.intStream(() ->
                Spliterators.spliterator(
                        new CharIterator(),
                        length(),
                        Spliterator.ORDERED),
                Spliterator.SUBSIZED | Spliterator.SIZED | Spliterator.ORDERED,
                false);
    }

codePoints()方法

这个方法是在jdk1.8新加的,先占个坑,之后再分析。

public default IntStream codePoints() {
        class CodePointIterator implements PrimitiveIterator.OfInt {
            int cur = 0;

            @Override
            public void forEachRemaining(IntConsumer block) {
                final int length = length();
                int i = cur;
                try {
                    while (i < length) {
                        char c1 = charAt(i++);
                        if (!Character.isHighSurrogate(c1) || i >= length) {
                            block.accept(c1);
                        } else {
                            char c2 = charAt(i);
                            if (Character.isLowSurrogate(c2)) {
                                i++;
                                block.accept(Character.toCodePoint(c1, c2));
                            } else {
                                block.accept(c1);
                            }
                        }
                    }
                } finally {
                    cur = i;
                }
            }

            public boolean hasNext() {
                return cur < length();
            }

            public int nextInt() {
                final int length = length();

                if (cur >= length) {
                    throw new NoSuchElementException();
                }
                char c1 = charAt(cur++);
                if (Character.isHighSurrogate(c1) && cur < length) {
                    char c2 = charAt(cur);
                    if (Character.isLowSurrogate(c2)) {
                        cur++;
                        return Character.toCodePoint(c1, c2);
                    }
                }
                return c1;
            }
        }

        return StreamSupport.intStream(() ->
                Spliterators.spliteratorUnknownSize(
                        new CodePointIterator(),
                        Spliterator.ORDERED),
                Spliterator.ORDERED,
                false);
    }

与String类的异同

String是CharSequence接口的一个实现,也就是说String也是CharSequence类型。

System.out.println(
    new String("string") instanceof CharSequence); // true