String,StringBuffer和StringBuilder这三个好基友
2017-03-07 16:23
323 查看
虽然在项目开发中,需要经常用上String处理字符串,但一直对它的理解还停留在如何使用的阶段,所以趁着这段时间复习一下,也写下博文希望把知识记得更深刻.
如有不正之处,请多多谅解和指正,谢谢.
String 变量名 = value
通过new实例化一个String对象
我们看以下例子
从这里看出s1和s2是分配到同一个内存空间里,而s3是另外一个内存空间,这两种方法虽然得出值都是Hello World但是他们的处理是大大不同的
如上图所示
其实当s1即将要被赋值的时候Jvm会看内存里是否存在Hello World这个值的内存空间,如果没有就直接创建该值的内存空间,将s1指向到这个内存空间当中
然后s2要被赋值时Jvm已经查到存储Hello World这个值的内存空间,所以也就直接将s2指向到这个内存空间当中
s3比较特别因为是它是通过new出来的一个实例,Jvm不会管内存里面是否已经存在Hello World这个内存空间,而是重新开辟一个空间让s3指向过去
所以最终得出这个结果.
从中我们可以看到String不管是类还是属性都被定义成final,所以每当我们对String对象进行从新赋值时,实际上就是改变内存空间的指向,而不是在原内存空间进行值的改变
很简单的道理,之前例子s1 和 s2 他们指向也是指向同一个内存空间,我改变了s2的值,因为s2指向的内存空间发生了变化,s1也会随这个变化而变化,最终导致我只想该s2结果也把s1的值也一起改了
这就是把String定义为final的原因
当做大量的字符串处理时通过String会消耗很多资源,一般我们做大量字符处理时,都会用上StringBuffer,StringBuilder这两个类
从源码中我们可以看到,不管在继承的类还是实现的接口都是一样的,唯一的不同是StringBuffer的append方法是带有synchronized,也就是说StringBuffer是线程安全的,而StringBuilder是线程非安全,因为String定义是final的关系,所以String天生就是线程安全的.
我们看下他们的执行效率
运行结果为
所以需要做到大量字符时
在不考虑线程的情况下优先StringBuilder,如果加大循环次数效果尤其明显
考虑线程的情况则使用StringBuffer但运行效率也是降低
如有不正之处,请多多谅解和指正,谢谢.
1.创建String内存空间
创建String对象基本有两种方法String 变量名 = value
通过new实例化一个String对象
我们看以下例子
public static void main(String[] args) { String s1 = "Hello World"; //第一种创建方法 String s2 = "Hello World"; String s3 = new String("Hello World"); //第二种创建方法 //String中的 == 是比较他们是否指向同一个内存空间 System.out.println(s1 == s2); //运行结果为ture System.out.println(s1 == s3); //运行结果为false }
从这里看出s1和s2是分配到同一个内存空间里,而s3是另外一个内存空间,这两种方法虽然得出值都是Hello World但是他们的处理是大大不同的
如上图所示
其实当s1即将要被赋值的时候Jvm会看内存里是否存在Hello World这个值的内存空间,如果没有就直接创建该值的内存空间,将s1指向到这个内存空间当中
然后s2要被赋值时Jvm已经查到存储Hello World这个值的内存空间,所以也就直接将s2指向到这个内存空间当中
s3比较特别因为是它是通过new出来的一个实例,Jvm不会管内存里面是否已经存在Hello World这个内存空间,而是重新开辟一个空间让s3指向过去
所以最终得出这个结果.
2.String是一个不可变类
当学习一个类最好的方法就是查看该类源码public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[]; private int hash; // Default to 0 private static final long serialVersionUID = -6849794470754667710L; private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; public String() { this.value = new char[0]; } ...... }
从中我们可以看到String不管是类还是属性都被定义成final,所以每当我们对String对象进行从新赋值时,实际上就是改变内存空间的指向,而不是在原内存空间进行值的改变
很简单的道理,之前例子s1 和 s2 他们指向也是指向同一个内存空间,我改变了s2的值,因为s2指向的内存空间发生了变化,s1也会随这个变化而变化,最终导致我只想该s2结果也把s1的值也一起改了
这就是把String定义为final的原因
3.String,StringBuffer,StringBuilder的区别
因为String是不可变类,无法对字符串进行直接的修改当做大量的字符串处理时通过String会消耗很多资源,一般我们做大量字符处理时,都会用上StringBuffer,StringBuilder这两个类
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence { ...... public synchronized StringBuffer append(String str) { super.append(str); return this; } }
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence { ...... public StringBuilder append(String str) { super.append(str); return this; } }
从源码中我们可以看到,不管在继承的类还是实现的接口都是一样的,唯一的不同是StringBuffer的append方法是带有synchronized,也就是说StringBuffer是线程安全的,而StringBuilder是线程非安全,因为String定义是final的关系,所以String天生就是线程安全的.
我们看下他们的执行效率
package com.rwj.test; public class StringDemo { public static void main(String[] args) { string(); stringBuffer(); stringBuilder(); } private static void string(){ long startTime = System.currentTimeMillis(); String s = new String(); for(int i = 0; i <= 100000; i++){ s += i; } long endTime = System.currentTimeMillis(); System.out.println("String: " + (endTime - startTime) + "毫秒."); } private static void stringBuffer(){ long startTime = System.currentTimeMillis(); //线程安全 StringBuffer s = new StringBuffer(); for(int i = 0; i <= 100000; i++){ s.append(i); } long endTime = System.currentTimeMillis(); System.out.println("StringBuffer: " + (endTime - startTime) + "毫秒."); } private static void stringBuilder(){ long startTime = System.currentTimeMillis(); //非线程安全 StringBuilder s = new StringBuilder(); for(int i = 0; i <= 100000; i++){ s.append(i); } long endTime = System.currentTimeMillis(); System.out.println("StringBuilder: " + (endTime - startTime) + "毫秒."); } }
运行结果为
所以需要做到大量字符时
在不考虑线程的情况下优先StringBuilder,如果加大循环次数效果尤其明显
考虑线程的情况则使用StringBuffer但运行效率也是降低
相关文章推荐
- 三个字符串类String、StringBuilder、StringBuffer的区别与比较
- Java中String, StringBuffer 和 StringBuilder 三个类的区别和联系
- String、StringBuffer和StringBuilder三个类的区别
- String,StringBuilder以及StringBuffer这三个类之间有什么区别
- String, StringBuffer, StringBuilder 三个类比较
- String, StringBuffer, StringBuilder 三个类比较
- 浅谈String、StringBuffer、StringBuilder的区别
- String,StringBuffer与StringBuilder的区别??
- String,StringBuffer与StringBuilder的区别
- String、StringBuffer和StringBuilder
- String、StringBuffer、与StringBuilder的区别
- 是String,StringBuffer还是StringBuilder?
- 深入理解String、StringBuffer、StringBuilder(转)
- String,StringBuffer与StringBuilder的区别??
- 是 String , StringBuffer 还是 StringBuilder ?
- String、StringBuilder、StringBuffer的区别
- <转>String、StringBuffer与StringBuilder之间区别
- String,StringBuffer与StringBuilder的区别详解
- String,StringBuffer与StringBuilder的区别??
- java面试题String,StringBuilder,StringBuffer