目录
(一)为什么要有String类
1.因为在编程中,对字符串的应用非常广泛,最常见的比如校验密码什么的,但是将数据和操作数据方法分离开的方式不符合面相对象的思想,所以就创造出了包含许多对字符串操作方法的String类。
(二)字符串的不可变性
String是不可变的,这也就意味着当一个字符串被创建好之后就不能再被修改了,jdk中也对此进行了明确的说明
翻译:字符串是一个常量,他们的值自从被创建后就不能被修改
任何看似修改字符串的操作实际上是开辟了一块新的空间来存放新的字符串
如在toUpperCase方法中,返回的是一个新创建的数组,而不是对原有字符串上的修改
(1)不能被修改原因
字符串就相当于被放进这个数组中,而这个数组是被private修饰的所以外界无法通过任何方式来对这个数组进行操作,于是这个也就成就了字符串的不可变性
(2)把字符串设计为不可修改的好处
1.线程安全:由于字符串是不可变的,一旦创建就不能被修改,因此它们可以安全地在多个线程之间共享而无需额外的同步
2.安全性:不可变性可以防止字符串被意外或恶意地修改。
3.优化:JVM和Java运行时环境可以对不可变对象进行优化。例如,由于字符串是不可变的,JVM可以安全地将它们存储在只读内存区域,或者对它们进行更高效的垃圾回收
(三)String是引用类型
如下代码我们创建一个String类型的变量
public class TestString {
public static void main(String[] args) {
String s1 = "hello";
}
}
此时在内存中存储的形势如图,s1中存放的不是hello的值,而是堆中真正存放hello值空间的地址,通过地址来找到hello(value)。
(四)字符串常量池
既然s1中存放的不是真正的值,而是堆中存放值的空间地址,那么s1 == s2返回的是false才对啊,为什么返回的是true呢。
如下图为实际情况
当String要创建一个对象时,会比较新创建对象中的值在字符串常量池中是否存在(hello),如果存在会直接将字符串中对象的地址复制给新创建的引用(s2),从而减少了创建对象的开销,提升了性能
(五)String类中的方法
String类中方法有很多,这里我只将常用的列举出来并表明用途,需特殊说明的会在旁边标注,不再具体演示。
棕色为返回值类型
1.查找
char charAt(int index):返回index位置上字符,如果index为负数或者越界,抛出 IndexOutOfBoundsException异常
int indexOf(int ch):返回ch第一次出现的位置,没有返回-1
int indexOf(int ch, int fromIndex):从fromIndex位置开始找ch第一次出现的位置,没有返回-1
int indexOf(String str):返回str第一次出现的位置,没有返回-1
int indexOf(String str, int fromIndex):从fromIndex位置开始找str第一次出现的位置,没有返回-1
int lastIndexOf(int ch):从后往前找,返回ch第一次出现的位置,没有返回-1
int lastIndexOf(int ch, int fromIndex): 从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返 回-1
int lastIndexOf(String str):从后往前找,返回str第一次出现的位置,没有返回-1
int lastIndexOf(String str, int fromIndex): 从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返 回-1
2.替换
String replaceAll(String regex, String replacement):替换所有的指定内容
String replaceFirst(String regex, String replacement):替换首个指定内容
3.拆分
String[] split(String regex):将字符串全部拆分 (如果一个字符串中有多个分隔符,可以用"|"作为连字符).
String[] split(String regex, int limit):将字符串以指定的格式,拆分为limit组
4.截取
String substring(int beginIndex):从指定索引截取到结尾
String substring(int beginIndex, int endIndex):截取部分内容
5.转化
String trim(): 去掉字符串中的左右空格,保留中间空格
String toUpperCase(): 字符串转大写
String toLowerCase(): 字符串转小写
String valueOf(Object obj): 将obj转化为字符串
char[] toCharArray(): 将字符串转化为数组
byte[] getBytes(): 使用平台的默认字符集将此 String
编码为字节序列,将结果存储到新的字节数组中
6.比较
重写Object类的方法
boolean equals(Object anObject):比较两个字符串的值是否相等
重写Comparable接口的方法
int compareTo(String s):对字符串中字符挨个比较,遇到不相同的返回,调用者字符-参数字符(Ascall码),若都相同,返回调用者长度-参数长度
public int compareTo(String anotherString) {
int len1 = value.length;//调用者长度
int len2 = anotherString.value.length;//参数长度
int lim = Math.min(len1, len2);//选取长度中的小值
char v1[] = value;//将调用者转换为数组
char v2[] = anotherString.value;//将参数转换为数组
int k = 0;//定义变量
while (k < lim) {//循环比较若不同返回调用者字符-参数字符
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;//若比较都相等返回调用者长度-参数长度
}
总结
1.字符串是不可变的
2.字符串是引用类型
3.字符串常量池可提升String类的性能(因为有了不可变性才有了常量池)
4.String类中提供了很多操作字符串的方法