Java小白-String
一、String的不可变性
为什么不可变?设计者认为可变字符串带来的灵活性<不可变带来的好处
好处:安全(网络传参、URL、HashMap key)、线程安全(多线程共用没风险)、可缓存(字符串常量池复用)
Java中的字符串是不可变的,但是你说oi,咋可能,我这不是变了吗,
public class Demo{public static void main(String[] args){String name = "ikun";name = "not_ikun";}
}
但这并不是字符串不变性的含义,它并没有改变内存中的字符串对象,而是在内存中的指向变为了not_ikun
我们接着说为什么不想更改这些字符串对象呢,因为它使Java能够保存大量的内存空间,比如当我们用anothername时,就会指向之前的ikun,如果不这样的话,我们在使用成百上千上万...个不同的变量,它们都具有完全相同的字符串值,就指向了同一个字符串值,大大节省了内存空间
public class Demo{public static void main(String[] args){String name = "ikun";String anothername = "ikun";}
}
怎么保证不可变?
final类:String被final修饰,不能被继承,不允许被改写
final数组:底层存储时private final char[](或新版本byte[] + 编码标志),指向地址不可变
没有暴露修改的方法:String没有setCharAt()之类的方法,内部方法也都是产生新对象,不会修改原对象
hashCode缓存:不可变可以安全缓存哈希值,提升性能。
二、字符串常量池(String Pool)
Java会把字面量字符串(也就是一样的)放在常量池中复用,通过==比较可以验证是否时同一个对象
public class Demo{public static void main(String[] args){String name = "ikun";String anothername = "ikun";System.out.println(name == anothername); // 这里打印会是true}
}
三、new String 与字面量的区别
public class Demo{public static void main(String[] args){String name = "ikun";String anothername = new String("ikun");System.out.println(name == anothername); // 这里打印会是false}
}
“ikun”在常量池,new String("ikun")在堆里重新创建一个对象,可以说它们并不是同一个ikun😏
四、常用的String方法
方法 | 作用 | 例子 |
---|---|---|
length() | 获取长度 | "abc".length() -> 3 |
charAt(int) | 返回指定位置字符 | "abc".charAt(1) -> 'b' |
equals(Object) | 比较内容 | "abc".equals("abc") |
equalsIgnoreCase() | 忽略大小写比较 | "Abc".equalsIgnoreCase("abc") |
substring(int) / substring(int, int) | 截取子串 | "abcdef".substring(2) -> "cdef" "abcdef".substring(2,4) -> "cd" |
indexOf(String) | 子串首次出现位置 | "abcabc".indexOf("bc") -> 1 |
lastIndexOf(String) | 子串最后出现位置 | "abcabc".lastIndexOf("bc") -> 4 |
contains(String) | 是否包含子串 | "abc".contains("b") -> true |
startsWith() | 是否以...开头 | "abc".startsWith("a") -> true |
endsWith() | 是否以...结尾 | "abc".endsWith("c") -> true |
replace() | 替换子串 | "abcabc".replace("a","x") -> "xbcxbc" |
split(String) | 按分隔符拆分 | "a,b,c".split(",") -> ["a","b","c"] |
trim() | 去除首尾空格 | " abc ".trim() -> "abc" |
toUpperCase() | 转大写 | "abc".toUpperCase() -> "ABC" |
toLowerCase() | 转小写 | "ABC".toLowerCase() -> "abc" |
valueOf() | 基本类型转字符串 | String.valueOf(123) -> "123" |
五、可变字符串StringBuilder 和 StringBuffer
Java-String StringBuilder StringBuffer有什么区别-CSDN博客
-
String
不可变,频繁拼接低效。 -
StringBuilder
:可变,单线程推荐,效率高。 -
StringBuffer
:可变,线程安全,老项目用得多,新项目少。