String是咱们常常用到的一个类型,其实有时候以为写程序就是在反复的操做字符串,这是C的特色,在java中,jdk很好的封装了关于字符串的操做。今天主要讲的是三个类String 、StringBuffer 、 StringBuilder .这三个类基本上知足了咱们在不一样情景下使用字符串的需求。java
先说,第一个String。面试
JDK的解释是 “Strings are constant; their values cannot be changed after they are created”也就是说String对象一旦被建立就是固定不变的了(你必定有问题,但请先等一等,耐心读下去),这样的一点好处就是能够多线程之间访问,由于只读不写。安全
通常状况下咱们如下面两种方式建立一个String对象多线程
两种方式是有区别的,这和java的内存管理有关,前面已经说过,string建立以后是不可变的,因此按照第一种方式建立的字符串会放在栈里,更确切的是常量池中,常量池就是用来保存在编译阶段肯定好了大小的数据,通常咱们定义的int等基本数据类型就保存在这里。app
其具体的一个流程就是,编译器首先检查常量池,看看有没有一个“string”,若是没有则建立。若是有的话,则则直接把str1指向那个位置。测试
第二种建立字符串的方法是经过new关键字,仍是java的内存分配,java会将new的对象放在堆中,这一部分对象是在运行时建立的对象。因此咱们每一次new的时候,都会建立不一样的对象,即使是堆中已经有了一个如出一辙的。ui
写一个小例子线程
String str1 = "string"; String str4 = "string"; String str2 = new String("string"); String str3 = new String("string"); /*用于测试两种建立字符串方式的区别*/ System.out.println(str1 == str4); System.out.println(str2 == str3); System.out.println(str3 == str1); str3 = str3.intern(); //一个不常见的方法 System.out.println(str3 == str1);
这个的运行结果是code
true //解释:两个字符串的内容彻底相同,于是指向常量池中的同一个区域对象
false //解释:每一次new都会建立一个新的对象
false // 解释: 注意==比较的是地址,不只仅是内容
true //介绍一下intern方法,这个方法会返回一个字符串在常量池中的一个地址,若是常量池中有与str3内容相同的string则返回那个地址,若是没有,则在常量池中建立一个string后再返回。实际上,str3如今指向了str1的地址。
这就是让人纠结的string了,如今你能够说话了。。。不少人有这样的疑问就是既然string是不变的,那么为何str1 + "some"是合法的,其实,每次对string进行修改,都会建立一个新的对象。
因此若是须要对一个字符串不断的修改的话,效率是很是的低的,由于堆的好处是能够动态的增长空间,劣势就是分配新的空间消耗是很大的,好比咱们看下面的测试。
long start = System.currentTimeMillis(); for(int i = 0; i < 50000; i++) { str1+= " "; } long end = System.currentTimeMillis(); System.out.println("the run time is "+(end -start)+" ms");
个人机器上运行结果是the run time is 3538 ms 若是你把循环的次数后面再增长几个0就会更慢。由于每一次循环都在建立心的对象,那么JDK如何解决这个问题?
下面就要说第二个类StringBuffer。
StringBuffer是一个线程安全的,就是多线程访问的可靠保证,最重要的是他是可变的,也就是说咱们要操做一个常常变化的字符串,可使用这个类,基本的方法就是append(与string的concat方法对应)和insert方法,至于怎么使用,就很少讲了,你们能够本身查看API。
StringBuilder sb = new StringBuilder("string builder"); StringBuffer sf = new StringBuffer("string buffer"); long start = System.currentTimeMillis(); for(int i = 0; i < 50000; i++) { //str1+= " "; sb.append(" "); } long end = System.currentTimeMillis(); System.out.println("the run time is "+(end -start)+" ms");
测试一下,此次只须要8ms,这就是效率。
那么接下来,就要问StringBuilder是干什么的,其实这个才是咱们尝使用的,这个就是在jdk 1.5版本后面添加的新的类,前面说StringBuffer是线程同步的,那么不少状况下,咱们只是使用一个线程,那个同步势必带来一个效率的问题,StringBuilder就是StringBuffer的非线程同步的版本,两者的方法差很少,只是一个线程安全(适用于多线程)一个没有线程安全(适用于单线程)。
其实看了一下jdk源代码就会发现,StringBuffer就是在各个方法上加上了关键字syncronized
以上就是对三个字符串类的一个总结,总之不要在这上面纠结。。。。。。不想介绍太多的方法,总以为那样会把一篇博客弄成API文档同样,并且还很是的繁琐。都是些体会,但愿有所帮助。起码不要再纠结,尤为是面试。。。。