使用如下

public class Main {

    public static void main(String[] args) {
        String Str = new String("hello  world");

        System.out.print("返回值 :" );
        System.out.println(Str.substring(4) );

        System.out.print("返回值 :" );
        System.out.println(Str.substring(4, 10) );
    }
}

源码

public String substring(int beginIndex) {
        // 当长度小于0的时候,直接抛出错误
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        // 获得子序列的长度
        int subLen = length() - beginIndex;
        // 如果子序列长度小于0,抛出错误
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        //如果长度为0,则返回原字符串
        if (beginIndex == 0) {
            return this;
        }
        // 否则返回
        // 先判断字符串是否为空,再次新建一个String字符串。
        return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
                          : StringUTF16.newString(value, beginIndex, subLen);
    }

进入 isLatinl

    private boolean isLatin1() {
        return COMPACT_STRINGS && coder == LATIN1;
    }

这个用于判断编码类型,判断为latin1编码还是UTF-8编码

进入StringUTF16.newString

此时假设传入的val的值为"1234567890"
index的值为4 len长度为6 返回的序列应该为567890

    public static String newString(byte[] val, int index, int len) {
     // 先判断COMPACT_STRINGS的值,该值是虚拟机的参数CompactString 默认的值为true,即,是用char保存,还是用byte保存,用来压缩内存空间,默认使用byte进行保存
        if (String.COMPACT_STRINGS) {
            // 因为默认为true,进入byte,调用compress ,使用byte
            byte[] buf = compress(val, index, len);
            if (buf != null) {
                // 当byte不为空的时候,新建字符串,然后进行包装
                return new String(buf, LATIN1);
            }
        }
        // 获得最后一个字符串长度,此时last的值的10
        int last = index + len;
        // 返回一个新建字符串,调用Arrays.copyOfRange进行复制。由于是节省内存空间,为一半字节,所以使用移位运算符全部除以2,编码形式为uft-8,其内部使用byte保存
        return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
    }

效果如下

--_093