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。线程非安全是指,当多个线程同时操作这个字符串的时候,可能发生脏的,重读或者其他错误的情况。相关文章推荐
- UIDatePicker && UIToolbar【时期选择器】
- CEGUI0.8.4例子
- UIBarButtonSystemItem样式
- UE4 蓝图RandomStreams
- Ibatis之3个不经常使用的Query方法
- iOS中UITextField详解
- iOS,UISlider
- [Vue warn]: Attribute "id" is ignored on component <div> because the component is a fragment instanc
- DruidDataSource配置 阿里数据源
- dragloader.js帮助你在页面原生滚动下实现Pull Request操作
- 移动Web单页应用开发实践——实现Pull to Request(上/下拉请求操作)
- Liquidfun的编译与运行
- [Vue warn]: Cannot find element: #main
- POJ 2524 Ubiquitous Religions(并查集)
- hibernate 中createQuery与createSQLQuery两个用法
- 自己定义UITabBarController
- UIActionSheet使用
- 已经被iOS9无情的抛弃了的UIAlertView
- UITableView解析
- [置顶] IOS 关于取消延迟执行函数的种种。performSelector与cancelPreviousPerformRequestsWithTarget