String是不可变对象
java.lang.String使用了final修饰,不能被继承字符串一旦创建,对象就无法改变,但字符串引用可以重新赋值。
String字符串常量池
java为了提高性能,静态字符串(字面量/常量/常量连接的结果)在常量池中创建对应重复的字符串直接量,JVM会首先在常量池中查找,如果存在即可返回对象,并不会创建新的对象,而是复用已有对象。
举个例子
String s1 = "hello"
String s2 = "hello"
Syestem.out.println(s1==s2);
输出:true
使用new创建字符串对象的方式创建字符串不会从常量池中获取
String str1 = "abc";
String str2 = new String("abc");//此时在堆上创建了一个新的String对象,将值拷贝为"hello"
String str3 = new String("abc");
System.out.println(str1 == str2);
System.out.println(str2 == str3);
输出:false
false
字符串拼接会开辟新的空间存储拼接后的字符串,直接比较字符串实际上是比较二者的地址
String s = "abc";
String s1 = "abcdef";
String s2 = s + "def";
输出:false
字符串的不可变性
- change的str --> main的data的hello
- 常量池没有"world",创建"world"
- change的str–> “world”
- test --> data所在的内存空间
- test将data内存空间下标0的地方进行了覆写
static String str = "hello";
static char[] data ={'a','b','c'};
public static void change(String str,char[] test){
str ="world";
test[0]='g';
}
public static void main(String[] args) {
change(str, data);
System.out.println(str);
System.out.println(Arrays.toString(data));
}
输出:hello
[g, b, c]
字符串无法修改本质原因:String对象内容实际上存储在内部value[]中,value[]是一个private+final,value指向的地址不可变。
要想修改字符串的内容只能通过反射破坏封装。
“hello”->“Hello”
public static void main(String[] args) {
String str ="hello";
Field fiel = String.class.getDeclaredField("value");
fiel.setAccessible(true);
char[] value=(char[])fiel.get(str);
value[0]='H';
System.out.println(str);
}
输出:Hello
大量修改字符串内容时,我们使用StringBuffer(线程安全)和StringBuilder(线程不安全)
StringBuilder
- String -> StringBuilder
- 通过StringBuilder的append方法或者构造方法传入字符串
- StringBuilder -> String
- 调用StringBuilder的toString
public static void main(String[] args) {
//String -> StringBuilder
//通过构造方法String -> StringBuilder
StringBuilder sb = new StringBuilder("hello");
//调用append方法将String -> StringBuilder
sb.append("world");
sb.append("!!!");
//此时StringBuilder内部存储的就是helloworld
//将StringBuilder还原为String
String res = sb.toString();
System.out.println(res);
}
输出:helloworld!!!
StringBuilder具备一些String不具备的方法(因为StringBuilder内容可修改,String内容不可修改)
StringBuilder常用方法
- reverse - 反转
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello World");
sb.reverse();
System.out.println(sb);
}
输出:dlroW olleH
- delete(int start,int end) - 删除指定范围的内容
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello World");
sb.delete(0,3);
System.out.println(sb);
}
输出:lo World
- insert(int start,插入的数据)
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello World");
sb.insert(3,"lalala");
System.out.println(sb);
}
输出:Hellalalalo World
String和char与byte的使用
- char:将String变成一个一个的字符,一般处理文本内容时使用
- byte:将String变成一个一个的字节,一般在网络传输中使用
字符串常用方法
- 字符串比较
int compareTo(String str)
- 判断一个字符是否存在
Boolean contains(String str)
- 字符串替换
replaceAll(int regex,String replacement)//将regex全部替换为replacement
- 字符串分隔
String[] split(regex)//将字符串按照regex拆分
String[] split(regex,limit)//将字符串按照regex拆分为最多limit个子串
- 按特殊字符拆分需要转义字符
- 字符串截取
String subString(int index1,int index2)//字符串截取某一片段,左闭右开区间
- 字符串去除两端空格
String trim();