Java的——String类、StringBuffer和StringBuilder、不可变和可变字符序列使用陷阱

Java的知识点21——String类、StringBuffer和StringBuilder、不可变和可变字符序列使用陷阱

原文链接 https://blog.csdn.net/qq_39368007/article/details/84033272


String类

String 类对象代表不可变的Unicode字符序列,因此我们可以将String对象称为“不可变对象”

substring()是对字符串的截取操作,但本质是读取原字符串内容生成了新的字符串

String测试代码


   
   
  1. package cn.dym10;
  2. public class test02 {
  3. public static void main(String[] args) {
  4. String s1= new String( "abcdef");
  5. String s2=s1.substring( 2, 4);
  6. System.out.println(Integer.toHexString(s1.hashCode()));
  7. // 打印:c61, 显然s1和s2不是同一个对象
  8. System.out.println(Integer.toHexString(s2.hashCode()));
  9. }
  10. }

 在遇到字符串常量之间的拼接时,编译器会做出优化,即在编译期间就会完成字符串的拼接。因此,在使用==进行String对象之间的比较时,需要特别注意

字符串常量拼接时的优化


   
   
  1. package cn.dym10;
  2. public class test03 {
  3. public static void main(String[] args) {
  4. //编译器做了优化,直接在编译的时候将字符串进行拼接
  5. String str1= "hello"+ " java"; //相当于str1="hello java"
  6. String str2= "hello java";
  7. System.out.println(str1==str2);
  8. String str3= "hello";
  9. String str4= " java";
  10. //编译的时候不知道变量中存储的是什么,所以没有办法在编译的时候优化
  11. String str5=str3+str4;
  12. System.out.println(str2==str5);
  13. }
  14. }

String类常用的方法有:

      1. String类的下述方法能创建并返回一个新的String对象: concat()、 replace()、substring()、 toLowerCase()、 toUpperCase()、trim()。

      2. 提供查找功能的有关方法: endsWith()、 startsWith()、 indexOf()、lastIndexOf()。

      3. 提供比较功能的方法: equals()、equalsIgnoreCase()、compareTo()。

      4. 其它方法: charAt() 、length()。


StringBuffer和StringBuilder

 StringBufferStringBuilder非常类似,均代表可变的字符序列。 这两个类都是抽象类 AbstractStringBuilder 的子类,方法几乎一模一样。

      1. StringBuffer JDK1.0版本提供的类,线程安全,做线程同步检查, 效率较低

      2. StringBuilder JDK1.5版本提供的类,线程不安全,不做线程同步检查,因此效率较高

常用方法列表:

      1. 重载的public StringBuilder append(“xxx”)方法

        可以为该StringBuilder 对象添加字符序列,仍然返回自身对象。

      2. 方法 public StringBuilder delete(int start,int end)

        可以删除从start开始到end-1为止的一段字符序列,仍然返回自身对象。

      3. 方法 public StringBuilder deleteCharAt(int index)

        移除此序列指定位置上的 char,仍然返回自身对象。

      4. 重载的public StringBuilder insert(int index,“xxx”)方法

        可以为该StringBuilder 对象在指定位置插入字符序列,仍然返回自身对象。

      5. 方法 public StringBuilder reverse()

        用于将字符序列逆序,仍然返回自身对象。

      6. 方法 public String toString() 返回此序列中数据的字符串表示形式。

      7. 和 String 类含义类似的方法:


   
   
  1. public int indexOf(String str)
  2. public int indexOf (String str,int fromIndex)
  3. public String substring (int start)
  4. public String substring (int start,int end)
  5. public int length ()
  6. char charAt (int index)

StringBuffer/StringBuilder基本用法: 


   
   
  1. package cn.dym10;
  2. public class TestStringBufferAndBuilder {
  3. public static void main(String[] args) {
  4. /**StringBuilder*/
  5. StringBuilder sb= new StringBuilder();
  6. for( int i= 0;i< 7;i++) {
  7. sb.append(( char)( 'a'+i)); //追加单个字符
  8. }
  9. System.out.println(sb.toString()); //转换成String输出
  10. sb.append( ",I can sing my abc!");
  11. System.out.println(sb.toString());
  12. /**StringBuffer*/
  13. StringBuffer sb2= new StringBuffer( "中华人民共和国");
  14. sb2.insert( 0, "爱").insert( 0, "我");
  15. System.out.println(sb2);
  16. sb2.delete( 0, 2); //删除子字符串
  17. System.out.println(sb2);
  18. sb2.deleteCharAt( 0).deleteCharAt( 0); //删除某个字符
  19. System.out.println(sb2.charAt( 0));
  20. System.out.println(sb2.reverse());
  21. }
  22. }


不可变和可变字符序列使用陷阱

String使用的陷阱:String一经初始化后,就不会再改变其内容了对String字符串的操作实际上是对其副本(原始拷贝)的操作,原来的字符串一点都没有改变。比如:

      String s ="a"; 创建了一个字符串

      s = s+"b"; 实际上原来的"a"字符串对象已经丢弃了,现在又产生了另一个字符串s+"b"(也就是"ab")。 如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的时间和空间性能,甚至会造成服务器的崩溃。

      相反,StringBuilder和StringBuffer类是对原字符串本身操作的,可以对字符串进行修改而不产生副本拷贝或者产生少量的副本。因此可以在循环中使用

String和StringBuilder在频繁字符串修改时效率测试:


   
   
  1. package cn.dym10;
  2. public class test04 {
  3. public static void main(String[] args) {
  4. //使用String进行字符串的拼接
  5. String str8= "";
  6. //本质上使用StringBuilder拼接,但是每次循环都会产生一个StringBuilder对象
  7. long num1=Runtime.getRuntime().freeMemory(); //获取系统剩余内存空间
  8. long time1=System.currentTimeMillis(); //获取系统的当前时间
  9. for( int i= 0;i< 5000;i++) {
  10. str8=str8+i; //相当于产生了5000个对象
  11. }
  12. long num2=Runtime.getRuntime().freeMemory();
  13. long time2=System.currentTimeMillis();
  14. System.out.println( "String占用内存:"+(num1-num2));
  15. System.out.println( "String占用时间:"+(time2-time1));
  16. //使用StringBuilder进行字符串的拼接
  17. StringBuilder sb1= new StringBuilder( "");
  18. long num3=Runtime.getRuntime().freeMemory();
  19. long time3=System.currentTimeMillis();
  20. for( int i= 0;i< 5000;i++) {
  21. sb1.append(i);
  22. }
  23. long num4=Runtime.getRuntime().freeMemory();
  24. long time4=System.currentTimeMillis();
  25. System.out.println( "StringBuilder占用内存:"+(num3-num4));
  26. System.out.println( "StringBuilder占用时间:"+(time4-time3));
  27. }
  28. }

要点:

      1. String:不可变字符序列。

      2. StringBuffer:可变字符序列,并且线程安全,但是效率低。

      3. StringBuilder:可变字符序列,线程不安全,但是效率高(一般用它)

猜你喜欢

转载自www.cnblogs.com/sunny3158/p/12181808.html
今日推荐