两种创建String对象的区别
String s1 = "hello"; String s2 = new String("hello");
s1是先查看常量池是否有 “hello” 数据空间,如果有就直接指向它,如果没有就创建然后指向它。s1最终指向的是常量池的空间地址。
s2是先在堆中创建空间,里面有value属性,指向常量池的 “hello” 空间,如果常量池没有 “hello” 则创建,如果有则通过value指向,s2最终指向的是堆中的空间地址。
s1和s2的内存布局
那我们来看下面的题目:
String a = "abc"; String b = "abc"; // true equals比较的是值是否相等 System.out.println(a.equals(b)); // true a和b的地址是一样的 System.out.println(a==b);
String a = "hello"; String b = new String("hello"); // true 比较的是值 System.out.println(a.equals(b)); // false 根据上面的内存布局可以看出a,b地址不一样 System.out.println(a==b); //b.intern() 返回的是常量池的地址 所以是 true System.out.println(a==b.intern()); //b指向堆中的地址,b.intern()返回的是常量池的地址所以是false System.out.println(b==b.intern());
String s1 = "hello java"; String s2 = "hello"; String s3 = "hello"; String s4 = new String("hello"); System.out.println(s2==s4); //false 地址不一样 System.out.println(s2==s3); //true 都指向常量池的hello空间 System.out.println(s2.equals(s3));// true 比较内容是否相等 System.out.println(s1==s2); // false 指向的常量池地址不一样
Person p1 = new Person(); p1.name = "小徐"; Person p2 = new Person(); p2.name = "小徐"; // 如图所示 地址相同 true System.out.println(p1.name==p2.name); //比较的是值是否相等 true System.out.println(p1.name.equals(p2.name)); //true System.out.println(p1.name=="小徐");
String类是一个final类,代表不可变的字符序列。字符串是不可变的,字符串对象一旦被分配,值就不可变。
String s = "java"; s = "hello";
上面的代码一共创建了两个对象
String s1 = "java"; String s2 = "hello"; //根据debug我们可以知道,先会创建一个StringBuilder对象, //然后后执行里面的append方法,最后调用toString String s3 = s1 + s2;
public class StringExcise02 { String str = new String("hello"); final char[] ch = {'j','a','v','a'}; public void change(String str,char[] ch) { str = "java"; ch[0] = 'x'; } public static void main(String[] args) { StringExcise02 ex= new StringExcise02(); ex.change(ex.str, ex.ch); System.out.println(ex.str + "end"); //helloend System.out.println(ex.ch); //xava } }
StringBuffer类
StringBuffer保存的是字符串变量,里面的值可以更改,每次更新不用创建新的对象,效率高于String。
String转StringBuffer
String str = "java"; //返回的stringBuffer才是StringBuffer对象,对str本身没有影响 StringBuffer stringBuffer = new StringBuffer(str); //使用append方法 StringBuffer stringBuffer1 = new StringBuffer(); stringBuffer1 = stringBuffer1.append("java");
StringBuffer转String
StringBuffer stringBuffer2 = new StringBuffer("java"); //使用StringBuffer提供的toString方法 String s = stringBuffer2.toString(); //使用构造器s String s1 = new String(stringBuffer2);
例题:把数字 234156.33 按示例 234,156.33 打印
public class StringExcise04 { public static void main(String[] args) { String price = "234156.33"; StringBuffer stringBuffer = new StringBuffer(price); for (int i = stringBuffer.lastIndexOf(".") - 3; i > 0; i -= 3) { stringBuffer = stringBuffer.insert(i, ","); } System.out.println(stringBuffer); } }
StringBuilder类
String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder。
String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:
String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
StringBuilder变为String: 调用toString()方法。
String、StringBuffer、StringBuilder的区别。
- String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
- StringBuffer与StringBuilder大部分功能是相似的
- StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作