java String 源码阅读笔记以及Unicode的学习
来源:互联网 发布:单片机c语言教程 编辑:程序博客网 时间:2024/04/30 01:14
感悟
可以看到String中的方法,均是比较简短的方法,且每一行的长度都在idea
代码显示框的一半长左右。非常便于阅读。
源码分析
string的不可变性
//从源码中可以看出string内部是通过数组实现的。其被final修饰, //即一旦定义就不会再发生改变 private final char value[];
regionMatches 比较两个字符串区域是否相等
public boolean regionMatches(boolean ignoreCase, int toffset, //...... while (len-- > 0) { //...... if (ignoreCase) { char u1 = Character.toUpperCase(c1); char u2 = Character.toUpperCase(c2); if (u1 == u2) { continue; } //注意这里,比较了大写后,依然要比较小写,对于格鲁吉亚 //字母,对大小写的规则比较特殊,要检查大小写全部检查才行 if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { continue; } } return false; } return true; }
split方法
对于将 . \转义字符作为分隔符需要使用split(“\.”) split(“\|”),否则其默认
使用空字符分割的
limit 参数控制模式应用的次数,因此影响结果数组的长度。如果该限制 n 大
于 0,则模式将被最多应用 n - 1 次,数组的长度将不会大于 n,而且数组的
最后项将包含超出最后匹配的定界符的所有输入。如果 n 为非正,则模式将
被应用尽可能多的次数,而且数组可以是任意长度。如果 n 为零,则模式将
被应用尽可能多的次数,数组可有任何长度,并且结尾空字符串将被丢弃。
public String[] split(String regex, int limit) { //当regex的长度为1且不是“.$|()[{^?*+\\”中的时或者当长度为2时 //且第一个字符为“\”转义字符,第二个字符不是字符0-9 a-z A-Z 以及 //utf-16之间的字符时,通过indexof处理,否则采用正则表达式处理 char ch = 0; if (((regex.value.length == 1 && ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || (regex.length() == 2 && regex.charAt(0) == '\\' && (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 && ((ch-'a')|('z'-ch)) < 0 && ((ch-'A')|('Z'-ch)) < 0)) && (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE)) { int off = 0; int next = 0; boolean limited = limit > 0; ArrayList<String> list = new ArrayList<>(); while ((next = indexOf(ch, off)) != -1) { if (!limited || list.size() < limit - 1) { list.add(substring(off, next)); off = next + 1; } else { // last one //assert (list.size() == limit - 1); list.add(substring(off, value.length)); off = value.length; break; } } // If no match was found, return this if (off == 0) return new String[]{this}; // Add remaining segment if (!limited || list.size() < limit) list.add(substring(off, value.length)); // Construct result int resultSize = list.size(); if (limit == 0) while (resultSize > 0 && list.get(resultSize - 1).length() == 0) resultSize--; String[] result = new String[resultSize]; return list.subList(0, resultSize).toArray(result); } return Pattern.compile(regex).split(this, limit); }
indexof方法
查找一个字符的位置
public int indexOf(int ch, int fromIndex) { //如果是普通字符 if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { final char[] value = this.value; for (int i = fromIndex; i < max; i++) { if (value[i] == ch) { return i; } } return -1; } else { //如果是汉字之类的字符 return indexOfSupplementary(ch, fromIndex); } }//根据i位置处的char,分别获得高位的btye值(放在char中)和低位的byte值和value数组比较 private int indexOfSupplementary(int ch, int fromIndex) { if (Character.isValidCodePoint(ch)) { final char[] value = this.value; final char hi = Character.highSurrogate(ch); final char lo = Character.lowSurrogate(ch); final int max = value.length - 1; for (int i = fromIndex; i < max; i++) { if (value[i] == hi && value[i + 1] == lo) { return i; } } } return -1; }
intern
一个和方法区相关的方法,在不同jdk版本中表现不一致(jdk6,jdk7),避免
使用吧。参考 http://blog.csdn.net/seu_calvin/article/details/52291082
string 相加的实现
a = a + b; //编译后会变成 (new StringBuilder()).append(a).append(b).toString(); //string是不可变的,这里生成了一个新的对象
关于java中的字符集
Unicode 只是字符集,而没有编码方式。其有一套标准,要求用1-4个字节来表示一个字符。
UTF-8 、UTF-16、UTF-32是 Unicode 字符集的编码方式
Unicode介绍
- Unicode的学名是”Universal Multiple-Octet Coded Character Set”,简
称为UCS,UCS可以看作是”Unicode Character Set”的缩写 - 在UCS编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE”的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符
- 在UCS编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE”的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,UCS规范建议在传输字节流前,先传输字符”ZERO WIDTH NO-BREAK SPACE”,如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的.字符”ZERO WIDTH NO-BREAK SPACE”又被称作BOM。
- 在 Java 中直接使用Unicode 转码时会按照UTF-16LE 的方式拆分,并加上 BOM。 如果采用 UTF-16 拆分,在 Java 中默认采用带有 BOM 的 UTF-16BE 拆分。
- 一个完整的Unicode字符叫代码点CodePoint,而一个Java char 叫代码单元code unit,占两个字节。
- string对象以UTF-16保存Unicode字符,需要用2个字符表示一个超大字符集。
- 汉字,这种表示方式为Sruuogate,第一个字符叫Surrogate High,第二个就是Surrogate Low。判断一个char是否是Surrogate区的字符,用Character的isHighSurrogate()/isLowSurrogate()方法。
- 我国本身的GB码(国标码)都没有把全部汉字收录,utf-16只是收录了常用的汉字。
bmp code
ISO 10646 定义了一个 31 位的字符集。然而,在这巨大的编码空间中,迄今为止只分配了前 65534 个码位 (0x0000 到 0xFFFD)。这个UCS的16位子集、称为基本多语言面 (Basic Multilingual Plane,BMP)。将被编码在16位BMP以外的字符都属于非常特殊的字符(比如象形文字),且只有专家在历史和科学领域里才会用到它们。按当前的计划,将来也许再也不会有字符被分配到从0x000000到0x10FFFF这个覆盖了超过100万个潜在的未来字符的 21 位的编码空间以外去了。
总结
Unicode和UTF-16:1个字符占2个字节(不管是哪国语言)
UTF-8:1个英文字符占1个字节,一个汉字(包括日文和韩文等)占3个字节
Java中的char默认采用Unicode编码,所以Java中char占2个字节
- java String 源码阅读笔记以及Unicode的学习
- java StringBuilder、stringbuffer、string 源码阅读笔记
- java.lang.String源码阅读笔记
- String源码阅读笔记
- JAVA源码阅读--String
- 阅读Java String源码遇到的问题
- Java框架类源码阅读学习笔记
- java+String源码阅读1
- java String源码阅读2
- Java源码阅读之String
- Java源码阅读-String类
- java源码阅读系列-String
- java源码阅读-java.lang.String(01)
- python string,Unicode和Qstring学习笔记
- JAVA源码String学习
- JAVA源码学习--String
- [Java]String类分析源码阅读
- Java String类 源码注释阅读
- jsp、freemarker、velocity
- OpenCV Tutorial: 色彩空間轉換(cvtColor)
- 麻省理工MIT计算机课程表
- Ajax get请求和post请求的封装
- 阅读《C++PrimerPlus》第六版中发现的印刷错误:4.35章节原始字符串(raw)
- java String 源码阅读笔记以及Unicode的学习
- 事件对象event
- Jsp-helloworld
- 第十周项目1-二叉树算法库
- 银联AMT机并不是所有带银联的银行卡都可以取钱使用的!
- 百度搜索功能
- HDU 1048 The Hardest Problem Ever
- char数组赋值
- Android中Fragment数据保存和恢复