• String、StringBuffer、StringBuilder区别


    最近我有了新的理解

    • String
    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        /** The value is used for character storage. */
        private final char value[];
    
        /** Cache the hash code for the string */
        private int hash; // Default to 0
    

    String 类中使用 final 关键字修饰字符数组来保存字符串,因此String对象不可变,这句话不正确
    我们知道被 final 关键字修饰的类不能被继承,修饰的方法不能被重写,修饰的变量是基本数据类型则值不能改变,修饰的变量是引用类型则不能再指向其他对象。因此,final 关键字修饰的数组保存字符串并不是 String 不可变的根本原因,因为这个数组保存的字符串是可变的。
    如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改。
    String 真正不可变有下面几点原因:

    • 保存字符串的数组被 final 修饰且为私有的,并且String 类没有提供/暴露修改这个字符串的方法.
    • String 类被 final 修饰导致其不能被继承,进而避免了子类破坏 String 不可变.
    • StringBuilder/StringBuffer
    abstract class AbstractStringBuilder implements Appendable, CharSequence {
        /**
         * The value is used for character storage.
         */
        char[] value;
    


    两者继承父类AbstractStringBuilder ,底层也是字符数组,当时没有private和final修饰,而且提供很多修改字符数组的方法

    • 线程安全性:String不可变,常量,安全,StringBuilder/StringBuffer都继承AbstractStringBuilder ,存在很多公共方法.但是StringBuffer 有同步锁,线程安全.反之,StringBuilder没有同步锁,不安全.
    • 性能:每次改变String的时候,都会新建String对象,浪费内存,降低性能.StringBuffer 有锁机制,原地改变,还是会浪费性能.StringBuilder不存在锁机制,原地改变,不考虑安全前提,性能好.
      总结:大数据,多线程,安全->StringBuffer ;大数据,单线程->StringBuilder;小数据,安全->String
       String str1 = "he";
            String str2 = "llo";
            String str3 = "world";
            String str4 = str1 + str2 + str3;
    
    // class version 52.0 (52)
    // access flags 0x21
    public class practice/begin/Code25_Demo {
    
      // compiled from: Code25_Demo.java
    
      // access flags 0x1
      public <init>()V
       L0
        LINENUMBER 8 L0
        ALOAD 0
        INVOKESPECIAL java/lang/Object.<init> ()V
        RETURN
       L1
        LOCALVARIABLE this Lpractice/begin/Code25_Demo; L0 L1 0
        MAXSTACK = 1
        MAXLOCALS = 1
    
      // access flags 0x9
      public static main([Ljava/lang/String;)V
       L0
        LINENUMBER 10 L0
        LDC "he"
        ASTORE 1
       L1
        LINENUMBER 11 L1
        LDC "llo"
        ASTORE 2
       L2
        LINENUMBER 12 L2
        LDC "world"
        ASTORE 3
       L3
        LINENUMBER 13 L3
        NEW java/lang/StringBuilder
        DUP
        INVOKESPECIAL java/lang/StringBuilder.<init> ()V
        ALOAD 1
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        ALOAD 2
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        ALOAD 3
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
        ASTORE 4
       L4
        LINENUMBER 15 L4
        RETURN
       L5
        LOCALVARIABLE args [Ljava/lang/String; L0 L5 0
        LOCALVARIABLE str1 Ljava/lang/String; L1 L5 1
        LOCALVARIABLE str2 Ljava/lang/String; L2 L5 2
        LOCALVARIABLE str3 Ljava/lang/String; L3 L5 3
        LOCALVARIABLE str4 Ljava/lang/String; L4 L5 4
        MAXSTACK = 2
        MAXLOCALS = 5
    }
    
    

    对象引用和“+”的字符串拼接方式,实际上是通过 StringBuilder 调用 append() 方法实现的,拼接完成之后调用 toString() 得到一个 String 对象 。

      String[] arr = {"he", "llo", "world"};
            String s = "";
            for (int i = 0; i < arr.length; i++) {
                s += arr[i];
            }
            System.out.println(s);
    
    // class version 52.0 (52)
    // access flags 0x21
    public class practice/begin/Code25_Demo {
    
      // compiled from: Code25_Demo.java
    
      // access flags 0x1
      public <init>()V
       L0
        LINENUMBER 8 L0
        ALOAD 0
        INVOKESPECIAL java/lang/Object.<init> ()V
        RETURN
       L1
        LOCALVARIABLE this Lpractice/begin/Code25_Demo; L0 L1 0
        MAXSTACK = 1
        MAXLOCALS = 1
    
      // access flags 0x9
      public static main([Ljava/lang/String;)V
       L0
        LINENUMBER 14 L0
        ICONST_3
        ANEWARRAY java/lang/String
        DUP
        ICONST_0
        LDC "he"
        AASTORE
        DUP
        ICONST_1
        LDC "llo"
        AASTORE
        DUP
        ICONST_2
        LDC "world"
        AASTORE
        ASTORE 1
       L1
        LINENUMBER 15 L1
        LDC ""
        ASTORE 2
       L2
        LINENUMBER 16 L2
        ICONST_0
        ISTORE 3
       L3
       FRAME APPEND [[Ljava/lang/String; java/lang/String I]
        ILOAD 3
        ALOAD 1
        ARRAYLENGTH
        IF_ICMPGE L4
       L5
        LINENUMBER 17 L5
        NEW java/lang/StringBuilder
        DUP
        INVOKESPECIAL java/lang/StringBuilder.<init> ()V
        ALOAD 2
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        ALOAD 1
        ILOAD 3
        AALOAD
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
        ASTORE 2
       L6
        LINENUMBER 16 L6
        IINC 3 1
        GOTO L3
       L4
        LINENUMBER 19 L4
       FRAME CHOP 1
        GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
        ALOAD 2
        INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
       L7
        LINENUMBER 22 L7
        RETURN
       L8
        LOCALVARIABLE i I L3 L4 3
        LOCALVARIABLE args [Ljava/lang/String; L0 L8 0
        LOCALVARIABLE arr [Ljava/lang/String; L1 L8 1
        LOCALVARIABLE s Ljava/lang/String; L2 L8 2
        MAXSTACK = 4
        MAXLOCALS = 4
    }
    
    

    编译器不会创建单个 StringBuilder 以复用,会导致创建过多的 StringBuilder 对象。浪费空间.因此,在循环中进行字符串拼接,直接使用StringBuilder比较好.

  • 相关阅读:
    Markdown入门
    JavaScript之bind,call,apply
    CentOS7中禁用IPV6
    How to install Shadow•socks in CentOS7
    How to install OpenBazaar Server in CentOS7
    array_map,array_walk的使用以及区别
    phpstudy 升级mysql 及MySQL服务等问题
    YII2 架构文章链接
    nginx 配置详解(新手必看)
    YII2常用笔记
  • 原文地址:https://www.cnblogs.com/shun998/p/15887464.html
Copyright © 2020-2023  润新知