目录
一、使用
String类是java程序设计中最常用的类之一,网上的资料也很多,在此只对其中部分方法加以介绍:
1、注意事项:
1)replace方法与replaceFirst和replaceAll不同,前者不支持正则表达式,而后二者是支持正则表达式的。
2)在使用split(String regex)和split(String regex, int limit)方法时要注意:
若要用.$|()[{^?*+\\之中的字符分割字符串,在指定regex参数时需要将其转义,否则得不到预期结果甚至出现异常。
2、以下方法虽然不是最常用的,但合理使用会给我们的操作带来方便:
public String(byte bytes[], String charsetName):常用于转换字符串编码格式,以解决乱码问题,如将从文件或网络获取到的字符串由ISO-8859-1编码格式转成UTF-8编码格式。
public String(byte bytes[], int offset, int length, String charsetName):转换编码格式并生成子串,常用于从格式文本中获取指定位置的信息。在不需要转换编码格式的情况下用substring()方法性能更好。
public boolean regionMatches(int toffset, String other, int ooffset, int len):判断两个字符串的局部是否相同。区分大小写。
public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len):功能与前一方法相同,是否区分大小写由一个参数决定。
public boolean startsWith(String prefix, int toffset):判断字符串从偏移位置开始是否由prefix指定的字符串开头,常用于格式化的文本。
public static String join(CharSequence delimiter, CharSequence... elements):用指定的分隔符将字符串拼接在一起。此种方式的性能比用StringBuffer稍微差点,但会比采用“+”和concat方法的性能要好很多(在1000个串相拼接的条件下进行的测试)。
二、实现机制
String类的实现中,有两个重要属性、二个重要辅助类和三个需要注意的方法:
1、两个重要属性:value属性和coder属性。
1)value属性:用于存放字符串中的字符,其声明形式为:private final byte[] value,即是一个私有的byte类型的数组,且该属性用了final修饰,说明其值是不能随意更改的(但可通过反射和字节码操作更改value所指的对象或其中的字符)。
value中存储的字符要么是Latin1字符,要么是UTF-16字符。若是Latin1字符,value的每个元素存放一个字符,下标0对应的元素存放第一个字符,如:"Sample"的存储形式为[83, 97, 109, 112, 108, 101];若是UTF-16字符,在value的每两个元素存放一个字符,小标小的存低8位,大的存高8位,如:"实例"的存储形式为[-98, 91, -117, 79]。
因此,length方法获取字符串长度时返回的是“value.length >> coder()”的值(coder方法返回0(Latin1)字符或1(UTF-16字符),右移一位相当于除以2)。
2)coder属性:指明此串是Latin1还是UTF-16。当值等于0时,说明是Latin1字符,等于1时为UTF-16字符。
2、重要辅助类:
1)StringLatin1:此类中操作都比较简单,如charAt方法的返回值是(char)(value[index] & 0xff)的结果,就是先取value数组中指定元素中的字符编码,然后只取低8位并转成字符返回;indexOf方法返回的是指定字符在value中的元素的下标;toLowerCase方法就是利用CharacterDataLatin1类的toLowerCase方法将value中的每一个字符转成小写并存于一个新的byte数组,然后根据新的byte数组生成一个新的String实例返回,等等。
2)StringUTF16:当coder的值为1时,String用此类处理字符串。与StringLatin1类的处理方式是相似的,重要的不同在于,获取长度时要将value的长度右移 1位,获取字符时要先分别获取低位8位和高8位的编码,然后在组合在一起并转成字符。
3、replaceFirst、replaceAll和split:
在第一部分中提到,这几个方法在使用要注意一些问题,大家看看其实现就知道了。
1)replaceFirst、replaceAll
public String replaceFirst(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceFirst(replacement); } |
public String replaceAll(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceAll(replacement); } |
从以上源码可以看出,replaceFirst和replaceAll方法的实现都采用了正则表达式,因此,要替换的符号是正则表达式用到的特殊符号,就必须转义,否则达不到预期效果。
2)split
public String[] split(String regex, int limit) { ...... return list.subList(0, resultSize).toArray(result); } return Pattern.compile(regex).split(this, limit); } |
从split方法的实现可以看出,若regex只包含一个字符,且是.$|()[{^?*+\\中的一员时,就当正则表达式处理;当regex式两个字符,且第一个字符不是\,或者第一个字符是\,而后一字符是数字或字母时,也被当做正则表达式处理。
另外,String类被声明成final形式,所以不能派生子类。
至于有关字符串的更深入的内容,在分析编译和jvm源码再分享。