您的位置:首页 > 产品设计 > UI/UE

java中的String,StringBuffer,StringBuilder

2015-12-29 20:17 627 查看

1、关于String类:

1、string的本质:



通过String的源代码能学到很多知识。



String类是一个常量,一旦创建后就不能改变。如果想要改变可以用String buffers的相关操作。

String的本质是由char字符组成的字符数组;

在注释中这样写:

String str =”abc”;

相于:

char data[]={‘a’,’b’,’c’};

String str =new String(data);

2、String与内存

首先要明确String在内存中的保存的地方:

1、字符串池;

2、堆;

3、常量池;

8种基本数据类型保存在栈中,通过new产生的对象实例保存在堆中。

String不属于基本数据类型。

String str=”abc”;创建保存到字符串池中对象;

String str1=new String(“abc”);创建的对象实例保存在堆中,另一个对象保存在常量池中;

public static void main(String[] args) {
// TODO Auto-generated method stub
String str = "abc";// 在字符串池中创建;
String str1 = "abc";// 在字符串池中创建;

String str2 = new String("abc");// 在堆中创建;
String str3 = new String("abc");// 在堆中创建;

String str4 = "a";// 在字符串池中创建;
String str5 = "bc";// 在字符串池中创建;
// 通过 + 链接的问题:
//问题1:如果链接的全部是字符串池中的,则不会创建新的对象
//问题2:如果链接的有不是字符串池中的,则会在堆创建新的对象;
String str6 = str4 + str5;
String str7 = "a" + "bc";//中会在字符串池中创建;
// true,str和str1都是在字符串池中的,字符串池中如果没有则会创建,如果有了则不会创建;
// 也就是str,str1是同一个对象
System.out.println("str:str1---- " + (str == str1));

// false; str在字符串池中,str2在堆中;
System.out.println("str:str2---- " + (str == str2));
// false;str2和str3分别为在堆中不同的对象;
System.out.println("str2:str3---- " + (str2 == str3));
// false;str为字符串池中的,str6最终形成的在堆内存中;
System.out.println("str:str6---- " + (str == str6));
// ture;str7全部是在字符串池中的,因此str与str7为同一对象;
System.out.println("str:str7---- " + (str == str7));
}


运行结果:



3、String创建对象的问题

经典问题: String str = new String(“abc”); 产生几个对象?

1、String str=”abc”;创建的对象保存在字符串池中,在字符串池中如果有了“abc”,则不会创建新的对象;

2、String str = new String(“abc”); 它的一个对象保存在堆中,另外还产生一个对象,就是在常量池是的对象。如果常量池中没有,则创建,如果有则不会创建。因此上面的问题是可能创建一个对象,也可能创建两个(在常量池中不存在的情况下)

3、String =”a”+”bc”;通过上面的可知,创建一个对象,在字符池中

4、字符串不可变产生的问题

String类这样的设计有很多的优点使用简单,易用,易维护和扩展。但在String的不可以变类,也带来也问题。对象一旦创建就不能改变内存状态,如果要把字符串连接或者改变,只能在串接后产生一个新的对象,也就是如果每执行一次串接都会创建新的对象,性能问题随之而来。

为了解决这个问题,便产生了StringBuffer。

5、StringBuffer

1、StringBuffer类:



继承于AbstractStringBuilder,下面对于StringBuffer的描述:



一个线程安全的可变序列

一个字符串缓冲区,但可以修改。在任何时候它包含一些特殊序列字符时,它的长度可以通过一些方法修改。

在多线程下字符串缓存是安全的。它的方法全部都是同步的。

构造:



在没有字符默认长度为16个字符大小;

2、StringBuffer是如何扩容的?

首先它调用父类方法:



在方法中又调用ensuerCapacityInternal();



最终走到这个方法中:



从StringBuffer中可以看出:

在这个方法中,首先开辟一个新的字符串大小,为 int newCapacity = value.length * 2 + 2;如果添加后的大小比这个还要大,则把添加后的大小直接给新。

6、StringBuilder

StringBuilder是非线程安全的,在jdk1.5提供的API。在这里不用多叙述StringBuilder,因为它和StringBuffer用法和内部实现原理基本一样,只是StringBuffer的方法前面一般都加上有synchronized。线程非安全是指,当多个线程同时操作这个字符串的时候,可能发生脏的,重读或者其他错误的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: