JAVA中String类详解
一、String的创建
String s1 = "hello world!";//第一种方式
String s2 = new String("hello world!");//第二种方式
java中String类型的创建有以上两种方式 .
第一种方式 :
创建的时候 , JVM会先在字符串常量池中去查找是否存在该字符串 , 如果存在直 接返回该字符 串对象的地址 , 否则会在常量池中创建该字符串对象并返回地址.
第二种方式 :
创建的时候 , 也会先查找常量池中是否存在该字 符串 , 如果存在就会在堆里面复制一份这个字符串对象,然后把堆里面的对象地址返回给变量.不存在的话就会在堆中和常量池中各创建一个对象 , 并返回堆中对象的地址 . (关于常量池的内容,请参考常量池);
例1:
String s1 = "zwz";
问该句代码创建了几个对象?
答案是1个,只在常量池中创建了一个对象.
例2:
String s1 =new String( "zwz");
问该句代码创建了几个对象?
答案是2个,在常量池和堆中各创建了一个对象.
例3:
String s1 = "zwz";
String s1 =new String( "zwz");
问这两句代码共创建了几个对象?
答案是2个,在常量池和堆中各创建了一个对象.
例4:
String s1 =new String( "cm");
String s1 =new String( "cm");
问这两句代码共创建了几个对象?
答案是3个,第一句在常量池和堆内存中各创建了一个对象,第二句由于常量池中存在字符串对象,所以仅在堆内存中创建了一个对象.
例5:
String s1 = "zwz"+"cm";
问这句代码共创建了几个对象?
答案是1个,“zwz”+"cm"在编译期就将字符串进行了连接,然后去常量池中查找有没有相同的字符串.
二、String常用的方法
①equals方法
用来比较两个字符串内容是否相同.
②charAt方法
返回指定索引处的字符
③contains方法
判断字符串中是否包含另一个字符串
④ indexOf方法
返回第一次出现某个字符串的位置
⑤isEmpty方法
判断字符串是否是空字符串
⑥split方法
将字符串分割,返回一个字符串数组
⑦trim方法
返回去掉字符串开头和结尾的空格后的字符串
⑧toCharArray方法
将字符串转换为字符数组
⑨replace方法
替换原字符串中的某个字符或子字符串,全部替换
⑩length方法
返回字符串的长度.
例子:
String string =" hello world!!";
System.out.println(string.charAt(1));
System.out.println(string.contains("he"));
System.out.println(string.indexOf("e"));
System.out.println(string.isEmpty());
System.out.println(string.split(" ")[0]);
System.out.println(string.trim());
System.out.println(string.toCharArray()[1]);//返回字符数组
System.out.println(string.replace("!", "?"));
System.out.println(string.length());
System.out.println(string.lastIndexOf("!"));
h
true
2
false
hello world!!
h
hello world??
14
13
重点介绍String的equals方法:
String类重写了equals方法,用来比较两个字符串的内容是否相同(和==做区分,==比较的是两个字符串对象的地址).
String类中equals具体是怎么实现的呢?
例:
s1.equals(s2)
实现:
首先调用==判断两个对象的地址是否相同,如果相同即是同一个对象,内容必定相同则返回true,
如果地址不相同则先判断传入的对象是否是String类的实例,如果不是直接返回false,
如果是String类的实例 则判断两个字符串的长度是否相等,不相等返回false,
如果长度相等的话就挨个比较两个字符串的字符数组,如果有一个不相同的话就返回false,都相同的话返回true.
看一下源码:
public boolean equals(Object anObject) {//anObject即为传入的String对象
if (this == anObject) {//首先调用==判断两个对象的地址是否相同,如果相同即是同一个对象,返回true
return true;
}
if (anObject instanceof String) {//如果地址不相同先判断传入的对象是否是String类的实例,如果不是直接返回false
String anotherString = (String)anObject;
int n = value.length;//value是字符串的字符数组
if (n == anotherString.value.length) {//判断两个字符串的长度是否相等,不相等返回false
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {//长度相等的话就挨个比较两个字符串的字符数组,如果有一个不相同的话就返回false,都相同的话返回true
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
三、StringBuilder、StringBuffer区别
StringBuffer和StringBuilder都继承自AbstraStringBuilder类,它们的使用方法都差不多.
只不过StringBuffer类大部分方法都加上了synchronized关键字 , 这说明StringBuffer类是线程安全的 . 而StringBuilder类方法上都没有加该关键字,所以当有多个线程同时操作StringBuilder对象时, 可能就会发生线程安全问题.即StringBuilder类是线程不安全的(synchronized详解)
因此:
需要线程安全就用StringBuffer,不需要就使用StringBuilder。
另外:
String的每次改变都会涉及到字符数组的复制,而StringBuffer和StringBuilder直接在字符数组上改变;同时,StringBuffer是线程安全的,而StringBuilder线程不安全,没有StringBuffer的同步,所以StringBuilder快于StringBuffer。
StringBuilder部分源码:
@Override
public StringBuilder append(char c) {
super.append(c);
return this;
}
StringBuffer部分源码:
@Override
public synchronized StringBuffer append(char c) {
toStringCache = null;
super.append(c);
return this;
}
同一种方法StringBuilder没有加上synchronized关键字,StringBuffer加上了synchronized关键字.
使用:
StringBuilder builder = new StringBuilder("hello world!!");
StringBuffer buffer = new StringBuffer("hello world!!");
StringBuilder append2 = builder.append("builder").delete(13, 20).insert(0, "builder:").reverse();
StringBuffer append = buffer.append("buffer").delete(13,19).insert(0, "buffer:").reverse();
System.out.println(append2);
System.out.println(append);
输出:
Builder:!!dlrow olleh:redliub
Buffer:!!dlrow olleh:reffub