StringBuffer类与StringBuilder类:
1. StringBuilder类是线程不安全的(效率高);StringBuffer类是线程安全的(效率较低);
2. StringBuffer类与StringBuilder类内的方法时一样的,作用一样,但线程效果不一样。
String类与StringBuffer类/StringBuilder类的区别:
1.String类底层使用final修饰的字符类型的数组,一经创建不可更改。每次更改创建新的对象,性能低;
2.StringBuffer类/StringBuilder类底层也是字符类型的数组,但没有使用final修饰,每次更改不需要创建新的对象,效率高。
原因是二者底层使用了动态数组结构,这种存在多余空间的结构保证了不会轻易的占满数组空间。
注:线程安全问题详见多线程.......
字符串是由多个字符组成的一串数据(字符序列),本质上是字符数组。
底层源码:private final char value[ ] ----------------- 使用final修饰是因为不希望String频繁的修改,这样会产生很多的垃圾。
字符串内存存储:
1.如果直接赋值,是存储在常量池中的,内容相同的字符串,只存一份,并且值不能变,如果重新赋值,相当于创建了一个新的变量;
2.使用new的方式创建的话,存储在堆空间中。
public class StringDemo2 {
public static void main(String[] args) {
String str = "hello"; //存放在常量池中
String str1 = new String("hello");// 存储在堆内存中
System.out.println(str == str1);//比较地址值,false
System.out.println(str.equals(str1));//因为String 重写了equals
System.out.println(str.hashCode() == str1.hashCode());//重写了hashCode.true
String str2 = new String("hello");//堆
System.out.println(str == str2);//false
System.out.println(str1 == str2);//false
String str3 = "hello";
System.out.println(str == str3);//true,相同内容的字符串,在常量池中只存一份
str = "hello1";
System.out.println(str == str3);//false:创建新的变量hello1存到了常量池,与原地址不同
String str5 = "hello";
change(str5);
System.out.println(str5);
}
private static void change(String str5) {
str5 = "helloworld";//创建新的变量,与原地址不同
}
}
注:byte数组和char数组都可以转成字符串, 用的都是String中的构造方法。
public class StringDemo1 {
public static void main(String[] args) {
String str = ""; //直接赋值的方式在常量池中开辟空间
String str1 = new String();
System.out.println(str1 == str); //false,二者的地址值不同
System.out.println(str1.equals(str)); //true,二者的地址值不同,但属性值均为空
System.out.println(str1); //空串,不是null。区别在于空串开辟了堆内存
byte[] bt = new byte[] {97,98,99,100};
String str2 = new String(bt); //通过构造方法将byte数组转化为字符串
System.out.println(str2); //abcd
String str3 = new String(bt,1,3); //1为索引值,3为长度
System.out.println(str3); //bcd
char[] ch = new char[] {'多','易','教','育'};
String str4 = new String(ch); //通过构造方法将字符数组转化为字符串
System.out.println(str4); //多易教育
String str5 = new String(ch,2,1); //2为索引值,1为个数
System.out.println(str5); //教
String str6 = new String("冰冻三尺,非一日之寒");
System.out.println(str6); //冰冻三尺,非一日之寒
}
}
注:使用已知字符串放在方法名前面,防止出现空指针异常。
public class StringDemo2 {
public static void main(String[] args) {
String s = "love";
System.out.println("love".equals(s)); //true
System.out.println("ABC".equalsIgnoreCase("abc")); //true
System.out.println("and you".contains("d y")); //true:注意空格
System.out.println("良好的开端是成功的一般".startsWith("良好")); //true
System.out.println("456.jpg".endsWith("jpg")); //true
String str1 = null; //地址值为空
System.out.println(str1 == null); //true
System.out.println(str1.isEmpty()); //异常:java.lang.NullPointerException
String str = new String(); //空串,不是null。二者的区别是是否开辟堆内存,而空串的地址值不为空,属性值为空。
System.out.println(str.equals("")); //true
System.out.println(str.isEmpty()); //true
}
}
public class StringDemo3 {
public static void main(String[] args) {
String s = "你若安好,便是晴天"; //在常量池中开辟空间
System.out.println(s.length()); //9:length()返回字符串的长度
char ch = s.charAt(2); //返回字符串索引位置为2的字符
System.out.println(ch); //安
//数组中的length是一个属性,没有括号。而字符串中的length()是一个方法。
for(int i=0;i
注:concat()方法: 只能拼接字符串
+: 可以拼接任意类型,包括对象,连接对象会自动调用对象的toString方法
我们在使用 + 拼接字符串的时候:
如果拼接的内容中存在变量:存放在堆内存中(底层使用new StringBuilder)
如果都是常量:存放在常量池中
public class StringDemo4 {
public static void main(String[] args) {
String s = "abc"; //英文字符
byte[] bt = s.getBytes(); //将字符串以byte数组类型返回
System.out.println(bt); //[B@7852e922
ArrayUtil.printArray(bt); //[97,98,99]:所有的数字都可以使用数字表示
String s1 = "燃"; //中文字符
byte[] bt1 = s1.getBytes();
System.out.println(bt1.length); //3。utf-8模式下中文占3个字节
System.out.println(bt1); //[B@4e25154f
ArrayUtil.printArray(bt1); //[-25,-121,-125]
System.out.println(new String(bt1)); //燃。程序会自动确认使用的是哪种编码格式
String s2 = "HBO";
char[] ch = s2.toCharArray(); //将字符串转为字符数组数组类型返回
System.out.println(ch); //HBO - println(char[] x):可以直接输出字符数组。
String s3 = String.valueOf(ch); //将字符数组转为字符串返回
System.out.println(s3); //HBO
System.out.println("abc".toUpperCase()); //将字符串中的小写字母转为大写
System.out.println("ABC".toLowerCase());
System.out.println("正午阳光".concat("骄阳似火")); //concat方法只能连接字符串
System.out.println("正午阳光" + "骄阳似火"); // + 可以连接任意数据类型
}
}
public class StringDemo5 {
public static void main(String[] args) {
String str = "天马流星拳";
System.out.println(str.replace('马', '吗')); //天吗流星拳 - 实现字符替换
String str1 = str.replace("天马","黄金天马"); //实现字符串替换
System.out.println(str1); //黄金天马流星拳
String str2 = " 56l 58 ";
System.out.println(str2.length()); //12
System.out.println(str2.trim().length()); //7 - trim()方法取出字符串两侧的空格
System.out.println(str2.trim()); //561 58
//按照字典顺序逐个进行对比,直至遇到不相等为止,返回差值。若均相等,则返回字符串长度的差值
System.out.println("abc".compareTo("abd")); //-1
System.out.println("abcd".compareTo("abc")); //1
System.out.println("abc".compareTo("abA")); //34
System.out.println("abc".compareToIgnoreCase("ABC")); //0:不区分大小写按照字典顺序比较
}
}
注:StringBuffer类与StringBuilder类中的方法一致,唯一的区别就是线程是否安全,StringBuffer中加入了同步锁synchronized,因此效率相对较低。以下只讲StringBuffer类......
String 和 StringBuffer/StringBuilder 相互转换:
1.String转StringBuffer/StringBuilder: 构造方法
2.StringBuilder/StringBuffer转String:toString
构造方法:
public StringBuffer() -------------- 空串
public StringBuffer(int capacity) -------------- 容量: 就是char数组的初始化长度,默认值是16
public StringBuffer(String str) ----------------直接输入字符串
相关成员方法:
public class StringBuilderDemo {
public static void main(String[] args) {
StringBuilder str = new StringBuilder(32);
System.out.println(str.length());//0: length:被使用的长度
StringBuilder str1 = new StringBuilder("大家下午好");
str1.append("凑合吧").append("也就那样"); //append():追加功能
System.out.println(str1); ////大家下午好凑合吧也就那样
System.out.println(str1.insert(1, "哈哈")); //大哈哈家下午好凑合吧也就那样 :插入功能
System.out.println(str1.deleteCharAt(0)); //哈哈家下午好凑合吧也就那样 :删除索引位置的字符
System.out.println(str1.delete(0, 2)); //家下午好凑合吧也就那样:删除从[start-end)
System.out.println(str1.replace(0, 2, "就这吧")); //就这吧午好凑合吧也就那样 :替换
System.out.println(str1.reverse()); //样那就也吧合凑好午吧这就 :逆序
StringBuilder str3 = new StringBuilder("abcde");
String re = str3.substring(3);
System.out.println(str3);//原内容不变, abcde
System.out.println(re);//de :字符串的截取,从索引位置为3开始截取
String re2 = str3.substring(0, 1); //从[0-1)进行截取
System.out.println(re2); //a
System.out.println(str3);//abcde
String s = str3.toString();
System.out.println(s); //abcde:toString()方法返回一个字符串对象
}
}