在正式介绍String以前,咱们先介绍下CharSequencephp
char + sequence 就是字符的序列的意思css
Java中万事万物都是对象类型vue
而对于字符的序列,也就是多个char, 这么一种东西, 使用CharSequence这个接口来描述ios
既然是接口,天然规定了做为字符序列的基本协议c++
char charAt(int index); | 返回指定索引的char |
int length() | 返回字符序列的长度 |
CharSequence subSequence(int start, int end) | 返回子序列 |
String toString() | 返回一个包含此序列中字符的字符串该字符串与此序列的顺序相同 |
default IntStream chars() | 返回此序列的int stream,每一个char零位扩展为int |
default IntStream codePoints() | 返回此序列的代码点的stream |
字符到字节,是一个编码的过程
字节到字符是一个解码的过程
|
一样的一个字符,在不一样的字符集和编码方式下,实际存储的值,将是不一样的
好比前面说的Unicode字符集,UTF8 和UTF16编码后的数据是不一样的
这个编码后的数据,也就是字节 , 他们是不同的
|
一样的一个编码值,在不一样的字符集中,可能表明着不一样的字符 |
因此字符与字节之间,必然有编码参与其中
这个编码环节是必然存在的,不然,你就没办法把字节与字符联系起来
![]() |
一个字符能够根据 字符集编码 进行多种方式的编码 一个字节数组也能够根据 字符集编码 进行多种方式的解码 对于同一个字符,无论进行何种编码,当他们按照当初编码的方式进行解码时,必然对应的仍是一样的那个字符 |
操做系统的文件都是以字节序列的形式存储的,因此任何一个文件都是有编码的 好比你在txt文件中输入了一个字符 这个字符 底层就会使用指定的编码存储到字节中 软件自己又把这个编码以字符的形式呈现出来 因此你才看获得是一个字符 好比这个文件中11111.txt中,存储了一个汉字春天的 " 春" 编码方式是UTF8 二进制软件查看是E6 98 A5 与咱们进行UTF8 编码计算的结果是对应的 ![]() |
ANSI编码 不一样的国家和地区制定了不一样的标准 由此产生了 GB23十二、GBK、Big五、Shift_JIS 等各自的编码标准 这些使用 1 至 4 个字节来表明一个字符的各类汉字延伸编码方式,称为 ANSI 编码 在简体中文Windows操做系统中,ANSI 编码表明 GBK 编码; 在日文Windows操做系统中,ANSI 编码表明 Shift_JIS 编码 再看下面一个例子 使用ultraedit 新建了一个文件,里面写了一个汉字 "春", 其实这个默认格式就是操做系统的编码,也就是ANSI 也就是GBK 查看二进制编码为 B4 BA 而后咱们再去对照GBK的码表,你会发现彻底对的上 ![]() |
任何一个文件,他其实有自带或者说默认的一个编码 凡是呈现字符的地方,都有一个编码在默默地支撑,才可以让你看得见,看得清楚字符 这个字符的保存 , 就是字符按照编码表 编码 成字节序列的过程 这个字符的呈现 , 就是字节序列按照编码表 解码 成字符的过程 当你使用计算机,进行字符处理工做的时候,无时无刻都在进行着编码与解码 |
String是经常使用类之一,因此提供了很是丰富的方法
String是字符序列 内部是char[] char就是一个十六进制的数 16位表示
因此char[] 能够用来构造String
|
char是16位数可以表示代码单元, int天然能够直接表示一个代码点了,因此也可使用int来构造String |
另外再加上咱们刚才关于字节数组与字符关系的介绍,也可使用字节数组构造String |
String() | 空String ,没啥必要由于String是不可变的![]() |
String(char[])
String(char[], int, int)
|
借助于字符数组或者字符数组的一部分建立对象 内部原本就是字符数组 char[] 因此天然可使用char[]构造 直接进行拷贝,因此对原有字符数组的修改不影响String对象 ![]() |
String(int[], int, int) | 使用代码点构造String public String(int[] codePoints, int offset, int count) offset 和 count为范围限制 |
String(String) | ![]() |
String(StringBuffer) | ![]() |
String(StringBuilder) | ![]() |
先提一下另一个方法,getBytes
使用指定的字符集将此 String 编码为 byte 序列
个人编辑器环境是UTF8编码的
"春" 的UTF8编码上面已经分析了
![]()
也就是说我这边有一个UTF8的字符"春" 源文件中保存的是 E6 98 A5
对于下面全部的getBytes来讲,"春" 这个字符形状符号是不变的
得到的字节数组就是 这个字符形状符号 根据不一样字符集编码方式, 编码而获得的字节数组
下面的各类转换换一个描述就是:UTF8的字符"春" ,在其余的字符集下面,编码都是多少啊?
|
![]() |
为何UTF-8 是-26 -104 -91 ? 而不是e6 98 a5?进制问题![]() |
getBytes总共三种形式 指定编码或者使用默认
getBytes(String)
getBytes(Charset)
getBytes()
还有一种已经弃用 了
|
使用byte[] 字节数组构造String的过程是下图这样子的 字节数组,根据指定字符编码转换为那个字符 而后在把字符按照UTF16 进行编码 存储到String中的char[] 上面的例子能够很好地印证这一点,字节数组是[-76, -70] 也就是 : ffffffb4 ffffffba 也就是 B4 BA 明明是GBK的"春" 根本就不是6625 对应关系就是他们表示的是同一个字符 |
![]() |
既然字节数组与字符的转换离不开编码,因此天然经过byte[] 构造String对象时,必需要有编码
不设定并非没有,而是使用默认的
既然使用字节数组,那么有的时候可能须要指定范围,因此有两个根本的构造方法
![]() |
而后还有默认字符编码的简化形式![]() |
再而后就是长度为整个字节数组的简化形式![]() |
这几个构造方法根本在于理解 字节数组与字符的转换 以及必须的byte[] 字节数组 以及 编码 |
copyValueOf方法内部就是直接调用的两个构造方法 还不如直接使用new建立来的直接,只不过使用这个方法有更好的可读性 |
![]() |
charAt(int) 返回指定索引处的 char 值 索引范围为从 0 到 length() - 1 简单粗暴, 无论三七二十一就是代码单元 若是是辅助平面,那就多是代理项 |
![]() |
codePointAt(int) 返回指定索引处的代码点, 范围从 0 到 length() - 1 他跟Character中的codePointAt方法逻辑含义是同样的 若是是高代理,若是下一个也在掌控范围内,若是下一个是低代理,那么返回代码点 不然,返回代码单元 也就是一个char ![]() |
codePointBefore(int) 返回指定索引以前的字符(Unicode 代码点) 其范围从 1 到 length 他跟Character中的codePointBefore方法逻辑含义是同样的 若是index-1 是低代理,若是在往前一个index-2 也是有效范围内,若是他还刚好是一个高代理,返回代码点 不然,返回代码单元,也就是一个char ![]() |
codePointCount(int, int) 此 String 的指定文本范围中的 Unicode 代码点数 文本范围始于指定的 beginIndex,一直到索引 endIndex - 1 处的 char, 包含头不包含尾 该文本范围的长度(用 char 表示)是 endIndex-beginIndex 因为一个代码点的代码单元个数多是1个多是2个,因此代码点的个数须要计算,就不直观了 他跟Character中的codePointCount方法逻辑含义是同样的 ![]() |
offsetByCodePoints(int, int) 他跟Character中的offsetByCodePoints方法逻辑含义是同样的 返回此 String 中从给定的 index 处偏移 codePointOffset 个代码点的索引 根本缘由仍是一个代码点的代码单元个数多是1个多是2个 因此 偏移codePointOffset个代码点的 代码单元的个数不肯定,须要调用方法计算 ![]() |
实例方法 就是一个复制方法,名字不太规范 复制String中指定索引开始的srcBegin 和 srcEnd 包含头不包含尾 到另外一个字节数组 char dst[]中, 存放的起始位置为dstBegin public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) |
须要注意的是,复制的是char 代码单元 就是String 内部char[] 的下标索引 |
startsWith(String, int)
startsWith(String)
|
实例方法 测试String是否以指定的前缀开始 还能够指定起始位置处开始比较 从源代码看得出来,挨个比较内部的char 从头开始,所有一致才返回true 单参数是双参数的简化版本 ![]() |
endsWith(String) | endwith就是从最后的指定参数长度的位置开始比较![]() |
int indexOf(int ch)
int indexOf(int ch, int fromIndex)
|
返回 指定字符 在此字符串中第一次出现处的索引 返回的匹配的第一个 也能够指定检索的起始位置, 若是指定了索引 那么返回的值将 大于等于 指定的索引 换个说法: 若是是0号平面返回的是那个代码单元也就是代码点的索引
charAt(k) == ch 为 true 的最小 k 值
若是是辅助平面返回的是高代理位的代码单元的索引 codePointAt(k) == ch 为 true 的最小 k 值 |
int indexOf(String str)
int indexOf(String str, int fromIndex)
|
返回 指定子字符串 在此字符串中第一次出现处的索引
返回匹配的第一个
也能够指定检索的起始位置,若是指定了索引
那么返回值须要大于等于 指定的索引
匹配的含义为startsWith(str) 为true
若是指定检索开始的位置, 那么
不只仅startsWith(str) 为true 还须要索引知足指定的下标范围
不然仍旧是返回-1
|
lastIndexOf(int)
lastIndexOf(int, int)
|
返回指定字符在此字符串中最后一次出现处的索引 返回匹配的最后一个 也能够指定检索位置,可是这个检索位置与indexOf不一样 indexOf中指定的索引,是从索引处日后 lastIndexOf指定的索引, 是反向,从索引处往前 指定了索引就要求 返回值 小于等于 指定索引 换个说法
若是是0号平面返回的是那个代码单元也就是代码点的索引
charAt(k) == ch 为 true 的最大 k 值
若是是辅助平面返回的是高代理位的代码单元的索引
codePointAt(k) == ch 为 true 的最大 k 值 而且 k 小于等于 指定的索引
|
lastIndexOf(String)
lastIndexOf(String, int)
|
返回指定 子字符串 在此字符串中最后一次出现处的索引
返回匹配的最后一个
也能够指定检索位置,检索索引的位置也是反向搜索
匹配的含义为startsWith(str) 为true
指定了索引就要求返回值 小于等于 指定索引
|