JDK源码解析<二> java.lang.String
2019-07-08 本文已影响0人
小吖么小一郎
String类用final修饰
- 实现字符串池: final修饰的string保证了string的不可变。字符串池要求字符串必须是不可变的。 字符串池的实现可以在运行时节约很多heap空间,因为不同的字符串变量都指向池中的同一个字符串。但如果字符串是可变的,那么String interning将不能实现,因为这样的话,如果变量改变了它的值,那么其它指向这个值的变量的值也会一起改变。
- 线程安全: String是final修饰,不能被继承和重写。因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的。
- 实现string创建hashcode不可变性: 因为字符串是不可变的,所以在它创建的时候HashCode就被缓存了,不需要重新计算。这就使得字符串很适合作为Map中的键,字符串的处理速度要快过其它的键对象。这就是HashMap中的键往往都使用字符串。
常用方法
- boolean endsWith(String suffix) 测试此字符串是否以指定的后缀结束。
- boolean equals(Object anObject) 将此字符串与指定的对象比较
- boolean equalsIgnoreCase(String anotherString) 将此 String 与另一个 String 比较,不考虑大小写
- int hashCode() 返回此字符串的哈希码
- int length() 返回此字符串的长度
- boolean matches(String regex) 告知此字符串是否匹配给定的正则表达式
- String replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的
- String replaceAll(String regex, String replacement) 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串
- String[] split(String regex) 根据给定正则表达式的匹配拆分此字符串。
- boolean startsWith(String prefix) 测试此字符串是否以指定的前缀开始 |
- String substring(int beginIndex, int endIndex) 返回一个新字符串,它通过开始角标,结束角标来截取获得
- String toLowerCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为小写 |
- String toString() 返回此对象本身
- String toUpperCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
- String trim() 返回字符串的副本,忽略前导空白和尾部空白
String , StringBuild, StringBuffer
效率: StringBuild > StringBuffer > String
线程安全: StringBuffer(安全), StringBuild(不安全)
- 在字符串不经常发生变化的业务场景优先使用String(代码更清晰简洁)。如常量的声明,少量的字符串操作(拼接,删除等)。
- 在单线程情况下,如有大量的字符串操作情况,应该使用StringBuilder来操作字符串。不能使用String"+"来拼接而是使用,避免产生大量无用的中间对象,耗费空间且执行效率低下(新建对象、回收对象花费大量时间)。如JSON的封装等。
- 在多线程情况下,如有大量的字符串操作情况,应该使用StringBuffer。如HTTP参数解析和封装等。
String长度
string里面ASCII字符最多只能有65534个。因为在class文件的规范中,CONSTANT_Utf8_info表中使用一个16位的无符号整数来记录字符串的长度的,最多能表示 65536个字节,而java class 文件是使用一种变体UTF-8格式来存放字符的,null值使用两个字节来表示,因此只剩下 65536- 2 = 65534个字节。也正是编体UTF-8的原因,如果字符串中含有中文等非ASCII字符,那么双引号中字符的数量会更少(一
个中文字符占用三个字节)。如果超出这个数量,在编译的时候编译器会报错