String,StringBuilder,StringBuffer总结
2016-09-29 10:40
274 查看
String:不可变字符序列 Stringbuilder和StringBuffer:可变字符序列三个类都在java.lang包,都是final类不可继承,都用char[]保存内容
String:
关于String s = "abc";和String s = new String("abc");
拘留字符串对象:equals相同的字符串对象,在堆内存中只会有一个拘留字符串对象。
String s = new String("abc");堆中两个对象:一个拘留对象一个普通对象。在此基础上加:String s2 = new String("abc"); 此时堆中一共三个对象(一个拘留两个普通)
String s = "abc"; 堆中只有一个拘留对象。在此基础上加:String s2 = "abc"; 此时堆中仍然只有一个拘留对象,两个引用指向同一个堆中地址。
“ab”+“cd” == “abcd”,true,一共三个拘留字符串对象,常量池中三个值;
String s = “ab”,s+“cd" == "abcd"; false,四个对象,其中三个拘留字符串对象,常量池中三个值。
String类中的源码:
private final char[] value; 所以String是不可变的,new出来的String对象进行操作“+”会new一个新对象然后改变引用(大量+导致效率低:JVM时间消耗主要在创建对象和回收对象)。
重写equals:
substring方法:先判断index是否正确,然后new了一个新String返回。
StringBuilder和StringBuffer:
异:StringBuffer中所有的insert、append、delete等方法都加了synchronized锁,保证多线程下的同步,但是影响效率;
StringBuilder是JDK1.5新增的,所有的方法都没有加锁。适用于单线程下的操作,效率比StringBuffer高。但是多线程下不能使用,会出现线程安全问题。
同:都继承自抽象类AbstractStringBuilder,大部分方法的实现都是在这个类里写的,两个实现类基本都是super调它的方法(有无synchronied)。
关于AbstractStringBuilder中的源码:
char[] value; 保存各字符;区别于String类少了private final的修饰。所以可以改value的引用地址,使这两个类看上去长度是可变的(长度不够数组扩容)。
append源码:
数组扩容的源码:
总结:不需要改变字符串的内容时,使用String,且尽量不要new对象;
需要改动字符串的内容时[b](增插删),单线程内使用StringBuilder,多线程使用StringBuffer。[/b]
String:
关于String s = "abc";和String s = new String("abc");
拘留字符串对象:equals相同的字符串对象,在堆内存中只会有一个拘留字符串对象。
String s = new String("abc");堆中两个对象:一个拘留对象一个普通对象。在此基础上加:String s2 = new String("abc"); 此时堆中一共三个对象(一个拘留两个普通)
String s = "abc"; 堆中只有一个拘留对象。在此基础上加:String s2 = "abc"; 此时堆中仍然只有一个拘留对象,两个引用指向同一个堆中地址。
“ab”+“cd” == “abcd”,true,一共三个拘留字符串对象,常量池中三个值;
String s = “ab”,s+“cd" == "abcd"; false,四个对象,其中三个拘留字符串对象,常量池中三个值。
String类中的源码:
private final char[] value; 所以String是不可变的,new出来的String对象进行操作“+”会new一个新对象然后改变引用(大量+导致效率低:JVM时间消耗主要在创建对象和回收对象)。
重写equals:
public boolean equals(Object anObject) { if (this == anObject) {<span style="white-space:pre">//先判断地址,是不是同一个对象 return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) {<span style="white-space:pre">//待比较对象是字符串且长度相同时,拿到String的value(字符数组),依次比较 char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }重写equals必重写hashcode。 源码中hashcode的值:h = 31 * h + val[i]; val表示String存内容的那个字符数组,字符数组多长循环多少次。
substring方法:先判断index是否正确,然后new了一个新String返回。
StringBuilder和StringBuffer:
异:StringBuffer中所有的insert、append、delete等方法都加了synchronized锁,保证多线程下的同步,但是影响效率;
StringBuilder是JDK1.5新增的,所有的方法都没有加锁。适用于单线程下的操作,效率比StringBuffer高。但是多线程下不能使用,会出现线程安全问题。
同:都继承自抽象类AbstractStringBuilder,大部分方法的实现都是在这个类里写的,两个实现类基本都是super调它的方法(有无synchronied)。
关于AbstractStringBuilder中的源码:
char[] value; 保存各字符;区别于String类少了private final的修饰。所以可以改value的引用地址,使这两个类看上去长度是可变的(长度不够数组扩容)。
append源码:
public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len);//保证不会超过当前数组的容量,超过则建新数组替换引用(因为数组长度是final,只能创建新的容量更大的数组,同时拷贝原来的数据) str.getChars(0, len, value, count);//将str放到value数组的最后(len)的位置。实现:System.arraycopy(),五个参数。 count += len; return this; }insert方法类似:判断形参、保证数组容量、System.arraycopy将目标索引后面的元素都向后移、str.getChars将新的str放到字符数组。
数组扩容的源码:
void expandCapacity(int minimumCapacity) { //形参的值:新字符串的实际长度 int newCapacity = value.length * 2 + 2; //扩容后的默认大小是原来数组长度的两倍+2 if (newCapacity - minimumCapacity < 0) //两倍+2 长度仍然不够新的实际长度 newCapacity = minimumCapacity; if (newCapacity < 0) { if (minimumCapacity < 0) throw new OutOfMemoryError(); newCapacity = Integer.MAX_VALUE; } value = Arrays.copyOf(value, newCapacity);//改变value的引用。原来那个char数组由于没有任何引用可以到达,下一次GC会被回收掉 }</span>
总结:不需要改变字符串的内容时,使用String,且尽量不要new对象;
需要改动字符串的内容时[b](增插删),单线程内使用StringBuilder,多线程使用StringBuffer。[/b]
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android之获取手机上的图片和视频缩略图thumbnails
- android string.xml文件中的整型和string型代替
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器