两种创建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未采用同步处理,属于线程不安全操作