public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];//用字符数组来保存
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
public String() {
this.value = "".value;
}
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
//......
}
被final修饰的类,表示不能被继承。方法用final修饰是为了不被覆盖。
再看String对象的初始化方法:
String s1=new String();//创建空字符串
String ss=new String("original");
String s2=new String(ss);//传入已有字符串
String s3=new String("abcdefg");
char[] ch=new char[]{'0','1','2','3','4','5','6','7','8'};
String s4=new String(ch);//传入字符数组
String s5=new String(ch,0,5);//将字符数组从0开始向后5个字符传入,01234
//基本数据类型可通过valueOf静态方法转换为字符串类型
char[] arr=new char[]{'h','e','l','l','o'};
String s6=String.valueOf(arr);//调用静态方法
//original
//abcdefg
//012345678
//01234
//hello
String的常用方法:
//求字符串的长度
public int length() {
return value.length;
}
//判断字符串是否非空
public boolean isEmpty() {
return value.length == 0;
}
//读取索引位置处的字符,但是不可修改
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
String str=new String("str");
s.concat(str);
System.out.println(s);//0123456789
System.out.println(s.concat(str));//0123456789str
将字符串str连接到0123456789之后,可见concat操作并未使原始字符串s发生变化,而是重新创建了一个String对象,因此String中的方法操作都不是在原有的字符串上进行的。下同
String s1=s.replace('0', 'A');
System.out.println(s1);//A123456789
String s2=s1.toLowerCase();
System.out.println(s2);//a123456789
由上可见,每修改一次字符串,就会创建一个新的String对象,在反复修改的场景下这是非常不环保的。因此当需要修改字符串对象时,大多选择使用StringBuilder或者StringBuffer。下面查看这两个类有何异同:
1、StringBuilder和StringBuffer都用final修饰;append、insert、reverse、toString等方法都差不多。
2、不同点在于,StringBuffer是线程安全的,方法用synchronized修饰。
链接中的文章详细说明了String,StringBuffer和StringBuilder的使用效率:
http://www.cnblogs.com/dolphin0520/p/3778589.htmllphin0520/p/3778589.html
讲的很清楚。
public static void main(String[] args) {
testString();
testStringBuilder();
testStringBuffer();
}
private static void testStringBuffer() {
String s="";
long start=System.currentTimeMillis();
for(int i=0;i<50000;i++){
s+="a";
}
long end=System.currentTimeMillis();
long time=end-start;
System.out.println("string: "+time);
}
private static void testStringBuilder() {
StringBuilder sbd=new StringBuilder();
long start=System.currentTimeMillis();
for(int i=0;i<50000;i++){
sbd.append("a");
}
long end=System.currentTimeMillis();
long time=end-start;
System.out.println("stringbuilder: "+time);
}
private static void testString() {
StringBuffer sbf=new StringBuffer();
long start=System.currentTimeMillis();
for(int i=0;i<50000;i++){
sbf.append("a");
}
long end=System.currentTimeMillis();
long time=end-start;
System.out.println("stringbuffer: "+time);
}
//stringbuffer: 4
//stringbuilder: 2
//string: 1127