Java String类的使用以及和StringBuffer和StringBuilder的区别
绪论
绪论:在Java语言中,为了处理字符串问题,Java提供了String,StringBuffer,StringBuilder三个类来封装处理字符串
String
String类是不可变类,一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁
- 为什么说String类是不可变类???
因为String类是字符串常量,常量那自然一旦创建就无法修改,看以下代码:
public class Test {
public static void main(String[] args) {
String str = "abc";
str = str+"ABC";
System.out.println(str);
}
}
输出结果:
有同学就要问了,这str明明被修改了啊,怎么就是不可变类了???
我们来看一下这段代码在JVM里面的状态:
字符串是被存储在方法区内存的字符串常量池里面的,因为开发人员考虑到,字符串在实际的开发中使用太频繁,为了执行效率,所以这么做。
》》在上述的代码中,出现了两串字符串(“abc"和"ABC”),所以在常量池中就会存储两串字符串,而 str = str+“ABC”;,得出的"abcABC"是由两个字符串所组成的第三个字符串,在存储在常量池后,str再抛弃对"abc"的指向,指向了"abcABC"。
字符串"abc"并没有被修改,被修改的只是str变量的保存内存地址,也就是对"abc"字符串的指向。因此说String是不可改变的类。
new String 和String
使用了new,是在堆内存里面开辟了空间,创建一个String的对象,str2指向String对象,String对象指向常量池中的"abc"。
注意:如果字符串常量池中已经存在了"abc",则把"abc"的内存地址直接赋给String对象,如果不存在,则先在常量池存储一个,再把内存地址赋给String对象。
public class Test{
public static void main(String[] args) {
String str = "abc";
str = str+"ABC";
String str2 = new String("abc");
}
}
内存图如下:
思考:
下列代码会输出true还是false????
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 ==str2);
当然是会输出true,"=="比较的是变量中的内存地址,str1和str2保存的都是字符串常量池中的"Hello"的内存地址。
好的,再次思考:
String x = new String("Hello");
String y = new String("Hello");
System.out.println(x == y);
答案是false,因为比较的是x和y变量所保存的是内存地址,也就是两个String对象的内存地址,他们是两个独立的String对象,内存地址当然不一样,所以会输出false
那么,下面这段代码会输出啥??
String x = new String("Hello");
String y = new String("Hello");
System.out.println(x.equals(y));
会输出true,为什么??因为String类已经重写了equals方法,比较的是String对象中存储的内容
总结:
String一次至少会创建0个对象
new String一次会创建至少1个对象
StringBuffer和StringBuilder
StringBuilder和StringBuffer的对象是可变字符串类,可以对对象进行更改
StringBuilder str = new StringBuilder();
str.append("abc");
str.append("ABC");
以上代码,会先在字符串常量池中存储一个"abc",然后会在堆内存中创建一个StringBuilder对象,str指向StringBuilder对象,StringBuilder指向”abc",在运行第三行代码后,常量池中的"abc"会被修改为"abcABC",StringBuilder和str的值都没有发生变化
区别
运行速度
StringBuilder >StringBuffer > String
解析:
因为String为字符串常量,不可以更改,每次对String对象进行操作实际上是不断创建新的字符串常量并且对旧对象进行回收的一个过程,所以执行速度自然慢
StringBuffer是线程安全的,StringBuilder是线程不安全的,一次StringBuffer需要处理的时间自然比StringBuilder要多
线程安全
StringBuffer中很多方法都带有synchronized关键字修饰,所以保证线程是安全的,但是StringBuilder则没有,在多线程的情况下建议使用StringBuffer。
总结
String:适用于少量字符串处理的情况
StringBuilder:适用于单线程,要求速度的情况
StringBuffer:适用于保证多线程安全的情况
附上三种类测试速度的代码:
public static void main(String[] args) {
long a=new Date().getTime();
String cc=""; int n=10000;
for (int i = 0; i < n; i++) {
cc+="."+i;
}
System.out.println("String使用的时间"+(System.currentTimeMillis()-a)/1000.0+"s");
long s1=System.currentTimeMillis();
StringBuilder sb=new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append("."+i);
}
System.out.println("StringBuilder使用的时间"+(System.currentTimeMillis()-s1)/1000.0+"s");
long s2=System.currentTimeMillis();
StringBuffer sbf=new StringBuffer();
for (int i = 0; i < n; i++) {
sbf.append("."+i);
}
System.out.println("StringBuffer使用的时间"+(System.currentTimeMillis()-s2)/1000.0+"s"); }
参考文献:https://www.cnblogs.com/weibanggang/p/9455926.html