• Java 基础 --- String, StringBuilder, StringBuffer


    String

    String的声明方式

    • 直接赋值: String s = “hello world” — 储存在常量池
    • 调用构造器 String s = new String(“hello world”) ---- 储存在堆中的地址
    • JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化, 为字符串开辟一个字符串常量池,类似于缓存区
    • 直接赋值时,首先坚持字符串常量池是否存在该字符串. 所以如果再次创建一个 String ss = "“hello world”. 将会和 s 指向同样的字符串常量
      在这里插入图片描述

    String的不可变性

    • String类声明为final, 所以不能被继承
    • String类实际储存字符串数据的是类内部的成员变量 final char [] value
    • 因为value被final修饰, 所以value不能指向新的地址也就是不能再引用其他String变量
    • String 内部没有改变 value 数组的方法,也就是不能更改String中任何一个char 元素, 因此可以保证 String 不可变。

    String不可变性的体现: 只要对string做出修改, 就会开辟新的内存空间

    • 1.当对字符串重新赋值时,会重新开辟新的内存空间储存新的字符串
    //常量池中会同时储存 "hello world" 和  "hello" , 而不是 "hello world" 被覆盖掉
    String s = "hello world"
    s = "hello" 
    
    • 1
    • 2
    • 3
    public static void main(String args[]) {
    	String s = "hello";
        String temp = s;
             
        s = "world"; 
        String ss = "hello";  
             
        if (ss == temp) {
           //注意这里对比的是地址, 说明ss和temp指向同样的地址
           //也就是 "hello" 没有被world覆盖掉
            System.out.println("same");
        }
    }
    output: "same"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 2.当对现有的字符串进行连接操作时,会重新开辟新的内存空间储存拼接后的字符串
    • 3.当调用String的replace(). 或者 substring() 等方法修改指定字符或字符串时,也会重新开辟新的内存空间储存修改后的字符串
    public static void main(String args[]) {
        String s = "hello";
        String temp1 = s;
        	
        s = s + "world" ;
        String temp2 = s;
             
        if (temp1 != temp2) {
            System.out.println("not same");
        }
    }
    
    output: "not same"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    对比两个String

    • 使用 == 对比两字符串时实际对比的是地址, 而不是实际内容
    • 所以一律使用 s1.equals(s2) 或者 s1.compareTo(s2) 对比string
    public static void main(String args[]) {
        String s = "hello";
        String ss = "hello";
        String sss = new String("hello");
        	
        System.out.println(s == ss);
        System.out.println(s == sss);
        System.out.println(ss == sss);
    }
    
    output:
    true // 因为 直接赋值创建String时, JVM会首先在常量池中寻找是否已经有同样的字符串. 所以s和ss指向同样的地址
    false //使用构造器创建String时, 地址会指向堆内存, 然后堆内存中的地址指向常量池, 所以不一样
    false //同上
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Another example:

    public class Solution {
    	
    	static public String fun1(String s1) {
        	return s1;
        }
          
        public static void main(String args[]) {
        	String s = "hello";
        	String ss = fun1(s);
        	System.out.println(s == ss);
        }
    }
    
    ouput: true
    //但是如果在fun1中对s1进行任何修改, 如拼接等, 就会开辟新的内存空间, 则 s != ss
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    StringBuilder

    • 如果代码中需要对string进行大量修改, 则推荐使用 StringBuilder类
    • StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象

    Example:

     public void pathToStartValue(TreeNode node, int startValue, String pathStart) {
     	if (node == null) {
        	return;
        }
            
        if (node.val == startValue) {
            pathTostartValue = pathStart;
            return;
        }
        
        //这里pathStart + "U" 会生成新的String, 最后导致内存超限
        //所以需要改用StringBuilder
        pathToStartValue(node.left, startValue, pathStart + "U");
        pathToStartValue(node.right, startValue, pathStart + "U");
            
        return;     
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • StringBuilder提供对String的增删改查, 包括:

    append:
    在这里插入图片描述
    insert
    在这里插入图片描述
    setCharAt

    void setCharAt(int index, char ch)
    //The character at the specified index is set to ch.
    
    • 1
    • 2

    delete

    StringBuilder	delete(int start, int end)
    //Removes the characters in a substring of this sequence.
    StringBuilder	deleteCharAt(int index)
    //Removes the char at the specified position in this sequence.
    
    • 1
    • 2
    • 3
    • 4

    replace

    StringBuilder	replace(int start, int end, String str)
    //Replaces the characters in a substring of this sequence with characters in the specified String.
    
    • 1
    • 2

    substring

    String	substring(int start)
    //Returns a new String that contains a subsequence of characters currently contained in this character sequence.
    String	substring(int start, int end)
    //Returns a new String that contains a subsequence of characters currently contained in this sequence.
    
    • 1
    • 2
    • 3
    • 4

    StringBuilder 和 StringBuffer 的区别

    • StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
    • 由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
  • 相关阅读:
    Ubuntu LabelMe AI 识别
    2022年最火的十大测试工具,你掌握了几个
    Ubuntu 23.10 支持基于 TPM 的全磁盘加密
    23种设计模式(二十二)状态模式(阁瑞钛伦特软件-九耶实训)
    解密Prompt系列18. LLM Agent之只有智能体的世界
    Android Camera App启动流程解析
    数据结构与算法——线性表的顺序存储
    spark-RDD的两大方法
    二维平面扭曲的python实现及思路
    OpenStack新版UI管理skyline
  • 原文地址:https://blog.csdn.net/weixin_38803409/article/details/126175948