社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
转自:
作者:海子
出处:http://www.cnblogs.com/dolphin0520/
对其中一些地方加入了自己的思考和整理,供自己和同学们学习参考。
要说Java中什么哪个类用的最频繁,要数String类了。关于String 、StringBuffer、StringBuilder是有必要详细研究一下的。
根据源码,可以得到:
由于源码冗长,不截图展示了,有兴趣的同学自己去查看,我是查看方法。
StringBuffer类也被定义成final类,与String类相同。但是StringBuffer类对象的字符序列是可修改的,类本身写好了方法改变序列类容和长度。并且StringBuffer是线程安全的,类的各个方法都用synchronized修饰。可以这样理解StringBuffer类:可修改的String,并且线程安全。(线程安全带来的缺点是效率相对StringBuilder而言更低)
JDK官方文档里是这样说的:一个可变的字符序列。 此类提供与StringBuffer的API,但不保证同步。 此类设计用作简易替换为StringBuffer在正在使用由单个线程字符串缓冲区的地方(如通常是这种情况)。 在可能的情况下,建议使用这个类别优先于StringBuffer ,因为它在大多数实现中将更快。 简单来说:StringBuilder是StringBuffer的特殊优化版本,不考虑线程安全,效率最高。
public class solution{
public static void main(String[] args){
String str = "hello";
for(int i=0;i<10000;i++){
str+= "world";
}
}
}
str+= "world"会被JVM优化成:
StringBuilder str = new StringBuilder(string);
str.append("hello");
str.toString();
因此,这三个类是各有利弊,应当根据不同的情况来进行选择使用:当字符串相加操作或者改动较少的情况下,建议使用 String str="hello"这种形式;当字符串相加操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer。
String a = "hello2";
String b = "hello" + 2;
System.out.println((a == b));
答:true。为什么呢?因为"hello" + 2在编译期间被优化成了"hello2",故运行期间a、b指向的是保存在常量池中的同一对象。
String a = "hello2";
String b = "hello";
String c = b + 2;
System.out.println((a == c));
答:false。由于有引用符号的存在,所有b + 2不会再编译期间被优化,不会吧b + 2当做字面常亮来处理,这种生成对象是保存在堆上。而a的对象是在常量池中。故a和c指向的并不是同一个对象。
String a = "hello2";
final String b = "hello";
String c = b + 2;
System.out.println((a == c));
答:true。对于被final修饰的变量,会在class文件常量池中保存一个副本,也就是说不会通过连接而进行访问,对final变量的访问在编译期间都会直接被替代为真实的值。那么String c = b + 2;在编译期间就会被优化成:String c = “hello” + 2。
public class Main {
public static void main(String[] args) {
String a = "hello2";
final String b = getHello();
String c = b + 2;
System.out.println((a == c));
}
public static String getHello() {
return "hello";
}
}
答:false。这里面虽然将b用final修饰了,但是由于其赋值是通过方法调用返回的,那么它的值只能在运行期间确定,因此a和c指向的不是同一个对象。
public class Main {
public static void main(String[] args) {
String a = "hello";
String b = new String("hello");
String c = new String("hello");
String d = b.intern();
System.out.println(a==b);
System.out.println(b==c);
System.out.println(b==d);
System.out.println(a==d);
}
}
答:false false false true。在String类中,intern方法(intern详解)是一个本地方法,在JAVA SE6之前,intern方法会在运行时常量池中查找是否存在内容相同的字符串,如果存在则返回指向该字符串的引用,如果不存在,则会将该字符串入池,并返回一个指向该字符串的引用。因此,a和d指向的是同一个对象。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!