zoukankan      html  css  js  c++  java
  • Java之String

    一、String,StringBuffer, StringBuilder 的区别是什么?String为什么是不可变的?###

    1. String是常量,它们的值在创建之后不能更改。(常量的定义:)
    2. 因为是常量,对String的+操作的重载存在问题。虽然通过引入StringBuilder优化过String的+,但是在循环中使用时,还是存在性能问题。

    public class StringTest {
        public static void main(String[] args) {
            String mango = "mango";
            String s = "abc"+ mango+ "def"+47;
            System.out.println(s);
        }
    }
    

    如上Java代码用javap -c Concatenation 解析出来如下:

    public class _13.CopyOfStringTest {
        public _13.CopyOfStringTest();
        Code:
           0: aload_0       
           1: invokespecial #8                  // Method java/lang/Object."<init>":()V
           4: return        
    
      public static void main(java.lang.String[]);
        Code:
           0: ldc           #16                 // String mango
           2: astore_1      
           3: new           #18                 // class java/lang/StringBuilder
           6: dup           
           7: ldc           #20                 // String abc
           9: invokespecial #22                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
          12: aload_1       
          13: invokevirtual #25                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          16: ldc           #29                 // String def
          18: invokevirtual #25                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          21: bipush        47
          23: invokevirtual #31                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
          26: invokevirtual #34                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          29: astore_2      
          30: getstatic     #38                 // Field java/lang/System.out:Ljava/io/PrintStream;
          33: aload_2       
          34: invokevirtual #44                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          37: return        
    }
    

    我们可以发现Java编译器的处理是,新建StringBuilder对象,使用该对象完成对字符串的+操作后,最终将StringBuilder转换成String返回。这一定程度上提高了,程序的处理效率。

    • 但是这并不意味着我们可以随意使用String对象,反正编译器可以为我们优化性能。从以下代码可以看出来:

      public class CopyOfStringTest {
      public String implicit(String[] fields) {
      String result = "";
      for (int i = 0; i < fields.length; i++) {
      result += fields[i];
      }
      return result;
      }

      public String explicit(String[] fields) {
      StringBuilder result = new StringBuilder();
      for (int i = 0; i < fields.length; i++) {
      result.append(fields[i]);
      }
      return result.toString();
      }
      }

    对其进行编译处理

    public class _13.CopyOfStringTest {
      public _13.CopyOfStringTest();
        Code:
           0: aload_0       
           1: invokespecial #8                  // Method java/lang/Object."<init>":()V
           4: return        
    
      public java.lang.String implicit(java.lang.String[]);
        Code:
           0: ldc           #16                 // String 
           2: astore_2      
           3: iconst_0      
           4: istore_3      
           5: goto          32
           8: new           #18                 // class java/lang/StringBuilder
          11: dup           
          12: aload_2       
          13: invokestatic  #20                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
          16: invokespecial #26                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
          19: aload_1       
          20: iload_3       
          21: aaload        
          22: invokevirtual #29                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          25: invokevirtual #33                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          28: astore_2      
          29: iinc          3, 1
          32: iload_3       
          33: aload_1       
          34: arraylength   
          35: if_icmplt     8
          38: aload_2       
          39: areturn       
    
      public java.lang.String explicit(java.lang.String[]);
        Code:
           0: new           #18                 // class java/lang/StringBuilder
           3: dup           
           4: invokespecial #45                 // Method java/lang/StringBuilder."<init>":()V
           7: astore_2      
           8: iconst_0      
           9: istore_3      
          10: goto          24
          13: aload_2       
          14: aload_1       
          15: iload_3       
          16: aaload        
          17: invokevirtual #29                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          20: pop           
          21: iinc          3, 1
          24: iload_3       
          25: aload_1       
          26: arraylength   
          27: if_icmplt     13
          30: aload_2       
          31: invokevirtual #33                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          34: areturn       
    }
    

    直接使用StringBuilder和使用String然后依靠编译器优化的区别为,一个是由编译器在循环内自动生成的StringBuilder,一个是在循环外手动创建的StringBuilder。很明显,在编译器自动优化时会产生大量的多余的StringBuilder对象。因此在循环中使用toString等操作时,最好自己创建一个StringBuilder对象。

    • StringBuilder的常用的方法有
      • append()
      • toString()
      • delete(int start包含, int end不包含)
    1. StringBuilder和StringBuffer的区别:

    StringBuffer是线程安全的,而StringBuilder是非线程安全的。ps:线程安全会带来额外的系统开销,所以StringBuilder的效率比StringBuffer高。如果对系统中的线程是否安全很掌握,可用StringBuilder,在线程不安全处加上关键字Synchronize。

  • 相关阅读:
    编译Openmv固件&增加串口
    边缘 AI 平台的比较
    CVPR2021 | 重新思考BatchNorm中的Batch
    ICCV2021 |重新思考人群中的计数和定位:一个纯粹基于点的框架
    ICCV2021 | 重新思考视觉transformers的空间维度
    CVPR2021 | Transformer用于End-to-End视频实例分割
    漫谈CUDA优化
    AAAI 2021 最佳论文公布
    综述专栏 | 姿态估计综述
    为什么GEMM是深度学习的核心
  • 原文地址:https://www.cnblogs.com/alcc/p/9201890.html
Copyright © 2011-2022 走看看