1.String
1.1 String介绍
Java为了处理字符序列引入String类,java把String类定义为final类,因此String类不可以有子类,用户不能拓展String类。
1.2 关于String对象
String常量
String常量是用双引号括起的字符序列,如:
"asasa"
"你好"
常量放在常量池中,由于常量也是对象,常量池中放着引用~~~~和实体,注意的是常量池在程序运行期间不允许改变。
对于常量向String对象的赋值,是把常量的引用赋值给String对象,如果给两个对象赋值相同的常量,如:
String s1="qwer";
String s2="qwer";
s1和s2里放着相同的引用,即"qwer"的引用
动态区 常量池
此时若是对s2进行新的赋值,不会改变常量池的内容(程序运行期间不变),而是改变动态区s2所存引用,如:
s2="qqqqq";
String对象
String类可以使用new来声明对象并创建对象。
String s1 =new String("ssssss");
String s2 =new String("ssssss");
s1和s2虽然赋值相同,但他们内部存储的引用不同。因为其用new运算符分配空间后存入字符序列,得到引用后赋值给s1和s2(new运算出的对象都不在常量池中)。
以下仅为目前的认知
对于String类来说,不管是使用常量赋值给String对象,还是用new运算符开辟空间,如:
String s1="qwe";
String s2=new String("qwer");
他们都会在常量池生成对应的字符串,只是s1是直接把在常量池的字符串对应的引用直接给s1,而s2是先在常量池中检查是否有“qwer”,如果没有,就在常量池中创建。然后再把其拷贝到堆中,把堆中的引用给s2。
如果用new创建多个相同的,如:
String s2=new String("qwer");
String s3=new String("qwer");
则在堆中拷贝对应的份数的字符串,然后把引用分别给对应的对象,因此比较时有如下情况:
String s1="qwe";
String s2="qwe";
s1==s2//true
String s3=new String("qwer");
String s4=new String("qwer");
s3==s4//false
1.3常用的构造方法
- String (char a[]) 把字符数组转化为字符串
char[] a={'a','a','a','w'};
String d=new String(a);
//等同于
String d=new String("aaaw");
- String (char a[],int startIndex,int count) 从数组的startIndex开始,提取count个字符,生成字符串
char[] a={'a','a','a','w'};
String d=new String(a,2,2);
//等同于
String d=new String("aw");
1.4字符串的并置
String对象可以用 "+" 进行并置运算
String s1="qw"
string s2="er"
String s3="qwer"
当两个常量并置时,结果仍是常量,常量池没有则放入。
string s4="qw"+"er";
s4==s3//true
但参与并置的有一个是变量时,则会在动态区存放得到的实体和引用
String s5=s1+"er";
s5==s3//false
因为其相当于
String s5=new String("qwer");
1.5 String类的常用方法
- public int length() 获取字符序列的长度
String s1="qwer";
int i=s1.length();//i=4
- public boolean equals(string s) 比较字符序列是否与指定对象的相同
public boolean equalsIgnoreCase(String s)比较时忽略大小写
String s1="qwer";
String s2="qwer";
String s3="QWER";
System.out.println(s1.equals(s2));//true
System.out.println(s1.equalsIgnoreCase(s3));//true
- public boolean startsWith(String s), public boolean endsWith(String s)
检查字符串是否以刚定的序列开始或者结尾
String s1="qwer";
System.out.println(s1.startsWith("qw")); //true
System.out.println(s1.endsWith("r")); //true
注意即使判定的只有一个字符也要用双引号
- public int compareTo(String s)
按字典序与s比较大小,相同返回0 ,大于s返回正值,小于返回负值
String s1="abcd";
System.out.println(s1.compareTo("abcd"));
System.out.println(s1.compareTo("ab"));
System.out.println(s1.compareTo("abcde"));
s1.compareToIgnoreCase() 忽略大小写
- public boolean contains(String s)
判断对象是否包含序列s
String s1="abcd";
System.out.println(s1.contains("ab"));
System.out.println(s1.contains("abd"));
- public int indexOf(String s)和public int lastIndexOf(String s)
当前对象从序列0开始,s第一次出现的位置和最后一次出现的位置,没有检索返回-1.
indexOf(String s,int startpoint),从指定位置startpoint开始检索(包含startpoint)
String s1="abcd";
System.out.println(s1.indexOf("b",1));
- public String substring(int startpoint)
复制从startpoint开始的,产生一个新的对象
public String substring(int start,int end)
复制从start到end-1位置上的字符
String s1="abcdfsdfd";
System.out.println(s1.substring(2,4));
- public String trim() 返回去掉前后空格的序列
String s1=" ab df d ";
System.out.println(s1.trim());
1.6 toString()
返回创建该对象类的名字@对象的引用的字符串表示
Dog a=new Dog();
System.out.println(a.toString());
Object的子类或间接子类可以重写该方法
2.StringBuffer
2.1StringBuffer介绍
String类对象的实体不可以改变,当修改字符时,实际修改的是引用。但StringBuffer类的对象的实体的内存可以改变,便于对字符的修改。
2.2构造方法
- StringBuffer();
初始分配容量为16个字符,当实体存放的大于16时,实体容量自动增加,可以通过length()方法获取当前字符的个数,capacity()方法获取实际容量。
- StringBuffer(int size);
通过指定size来分配其初始容量
- StringBuffer(String s);
分配给s的字符序列长度再加16
StringBuffer a=new StringBuffer("qwe");
System.out.println(a.length());
System.out.println(a.capacity())
2.3 常用方法
- append方法
- StringBuffer append(String s);
将s追加到当前序列中
- StringBuffer append(int n);
将int型转化为String对象后追加
类似的还有long,boolean等类型
- public char charAt(int n);和public void setCharAt(int n,char ch);
第一个是返回位置n上的字符
第二个是将位置n上的字符用ch替换,n为非负数
- StringBuffer insert(int index,String str)
将str插入到指定位置index
- public StringBuffer reverse()
将字符序列翻转
- StringBuffer delete(int startIndex,int endIndex)
删除startIndex到endIndex-1的子序列
deleteCharAt(int index)
删除指定位置
- StringBuffer replace(int startIndex,int endIndex,String str)
将子序列用str替换,str长度不需要和替换掉的相同
StringBuffer a = new StringBuffer("qwe");
System.out.println(a.replace(0, 1, "sssss"));
3.StringBuilder
3.1StringBuilder简介
StringBuilder是一个可变的字符序列。此类提供一个与 StringBuffer 兼容的API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。
在大多数实现中,它比 StringBuffer 要快,因此建议优先采用该类。 在 StringBuilder 上的主要操作是 append 和 insert 方法。也具备自动扩容功能。StringBuilder类可以用于在无需创建一个新的字符串对象情况下修改字符串。StringBuilder不是线程安全的,而StringBuffer是线程安全的。但StringBuilder在单线程中的性能比StringBuffer高。因此合理选择使用。
3.2 常用方法
StringBuilder的常用方法和StringBuffer的一样。
3.3构造方法
StringBuilder() value内容为空,并设置容量为16个字节;
StringBuilder(CharSequece seq) 使用seq初始化,容量在此基础上加16;
StringBuilder(int capacity) 设置特定容量;
StringBuilder(String str) 使用str初始化,容量str大小的基础上加16;
4.三者区别
主要存在以下两个方面的区别:运行速度、线程安全。
4.1运行速度(执行速度)
运行速度的快慢:StringBuilder > StringBuffer > String。
4.2 线程安全
StringBuilder 是线程不安全的,而 StringBuffer 是线程安全的。
如果一个 StringBuffer 对象在字符串缓冲区被多个线程使用时,StringBuffer 中很多方法可以带有 synchronized 关键字,所以可以保证线程是安全的。但 StringBuilder 的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以在多线程环境下操作用 StringBuffer,在单线程环境下操作,还是建议使用速度比较快的 StringBuilder。
三、小结
- 操作少量的字符串数据 用 String;
- 单线程下字符缓冲区中的大量操作 用 StringBuilder(推荐使用);
- 多线程下字符缓冲区中的大量操作 用 StringBuffer。