1.String类
1)String代表字符串类型,字符串的本身内容不可改变,字符串存储于“字符串常量池”中。
2)String的两种实例化方式:
a.直接赋值法
例如:String str="Hello";
b.通过new操作符实例化
例如:String str=new String("Hello");
将常量池中的内容赋值一份到堆内存中
3)一个字符串就是一个String类的匿名对象。(匿名对象就是在堆内存中开辟了空间,但在栈内存中并没有引用指向的对象)
4)字符串的常用方法:
a.public String(byte[] bytes) //使用平台的默认字符集解码,将字符数组转换为字符串
b.public String(byte[] bytes,Charset charset) //使用指定字符集解码,将字节数组转换成字符串
c.public char charAt(int index) //根据索引位置获取字符串中的某个字符
d.public boolean contains(CharSequence s) //判断当前对象代表的字符串是否包含参数字符串内容
e.public boolean equals(Object obj) //判断字符串内容是否相等
f.public byte[] getBytes() //将字符串转换为字节数组
h.public int indexOf(String str) //返回参数字符串在当前字符串中的索引位置
i.public int length() //返回当前字符串的长度
j.public String toLowerCase() //将字符串转换为小写
k.public String toUpperCase() //将字符串转换为大写
l.public char[] toCharArray() //将字符串转化为字符数组
m.public String substring(int beginIndex) //从beginIndex位置开始,到字符串末尾,截取字符串
n.public String substring(int beginIndex,int endIndex) //从beginIndex索引位置开始到endIndex-1,截取字符串
o.public String trim() //返回一个字符串,这个字符串删除了前导和尾随空格
p.public String[] split(String regrx) //通过指定的整个表达式拆分字符串,将拆分后的结果作为一个字符串数组返回
陷阱问题:
public class StringDemo {
public static void main(String[] args) {
String str="hello";
change(str);
System.out.println(str);
}
public static void change(String str){
str="中国";
}
}
最后输出的应该是Hello。(原理是str(拷贝)会在字符串常量池中寻找“中国”,如果存在,则指向该字符串,反之将“中国”加入字符串常量池中)
public class PersonTest {
public static void main(String[] args) {
Person per=new Person("张三");
changePerson(per);
System.out.println(per);
}
public static void changePerson(Person per){
per.setName("李四");
}
}
最后输出的应该是李四(代码的执行过程是:首先开辟一块空间,栈内存中的引用指向堆内存中刚开辟的这块空间,将“张三”从字符串常量池中赋值一份送到这块空间中,当调用changePerson(per)函数时,是将per拷贝一份,per与per(拷贝)指向同一个地址,但改变per(拷贝)所指向的地址中内容时,per所指向的内容也会发生改变,所以最后输出“李四”)。
最后一个问题:
String str="Hello";
String str1="Hello";
String str2=new String("Hello");
System.out.println(str==str1); //输出true,str指向常量池中的“Hello”,str1在常量池中也找到了“Hello”,所以str与str1指向同一个地址(注意:==在这里比较的是地址是否一样))
System.out.println(str.equals(str1)); //String类重写了equals方法,所以在这里比较的是内容是否相等
System.out.println(str==str2); //输出false,str指向常量池中的“Hello”,而str2是在堆内存中开辟一块空间,然后将常量池中的“Hello”复制一份到刚开辟的空间中,所以str与str2指向不同的地址
2.StringBuffer类(线程安全)
StringBuffer代表可变的字符序列。
StringBuffer称为“字符串缓冲区”,工作原理:预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓冲区的大小,以容纳更多的字符序列
StringBuffer是可变对象,与String最大的不同是,如果连续操作String对象会产生大量垃圾,而且断开-连接很频繁,既浪费时间也浪费空间,而StringBuffer就解决了这个问题,它只需要连接一次,也不会产生垃圾数据。
3.StringBuilder(线程不安全)
StringBuilder与StringBuffer功能几乎是一样的,只是StringBuilder线程不安全,而StringBuffer线程安全