Java中采用了UTF-16的格式, 该格式中使用两个字节表示一个基本字符, 所以Java中的char类型占用的存储空间也就是两个字节, 可两个字节最多也就表示60000多个字符, 而Unicode中现在收录了超过了14万个字符, 那么剩下的字符是如何表示的?
Java中如果是将一个辅助字符放到一个char中的时候就会编译出错, 因为我们的辅助字符需要使用两个代码单元, 也就是四个字节来表示, 而我们的一个char知识两个字节, 所以我们对于辅助字符要使用字符串变量来接收(String底层会使用两个代码单元, 也就是四个字节来存储一个辅助字符)
我们如果调用charAt()方法获取某个位置的字符的时候如果是获取到了某个辅助字符的一对char中的一个的时候就会出现乱码
如果我们一个字符串中有辅助字符, 那么我们调用length()方法获取结果的时候同样会有一定的问题, 因为字符串中的length()方法其实是获取到代码单元的数量, 而一个辅助字符占用了两个代码单元
如果字符串中有辅助字符, 并且这个时候我们要求出字符串的真正长度的时候, 我们可以通过码点的形式来获取, 一个码点就是代表了一个字符
使用Character类中的isSupplementaryCodePoint()方法判断参数码点是否是表示一个辅助字符
使用Character类的isSurrogate()方法判断参数char是否是一个辅助字符的一个代码单元
我们在前端向服务器发送一个请求的时候如果请求数据中是24个英文字母, 这个时候我们在请求头中的content-length中可以看到这24个英文字母占用的字节数是24个字节, 就是说这个时候就是使用的utf-8编码进行存储的, 此时到了java中就是外码(utf-8)
但是当将这个字符串传输到Java中的时候如果保存到一个String变量中的时候, 这个字符串的长度就不是24个字节了, 而是48个字节, 因为存储到内存中的时候就是使用的内码了, 而Java中的内码是UTF-16, 在UTF-16中除了辅助字符之外的字符都是占用了两个字节, 只有辅助字符是占用了4个字节的, 所以这也就是为什么我们将这个字符串保存之后可以计算出字符串长度为24了, 我们的length()方法是通过代码单元进行分割的,而一个代码单元占两个字节
length(),charAt()方法等等很多方法都是使用代码单元进行的分割, 而不是码点, 所以对于这种方法操作的字符串中一定不能有辅助字符, 否则就会出问题, 因为辅助字符是使用4个字节, 也就是两个代码单元存储的