Java学习笔记:String、StringBuilder与StringBuffer

String类是Java内置的用来表示字符串的类,所有的字面量字符串,都是String类的实例实现。当然,我们也可以通过new一个新对象的方式,创建一个String实例。

java 复制代码
public class App {  
    public static void main(String[] args) {  
        // 方式1:使用字面量  
        String s1 = "hello";  
        // 方式2:new  
        String s2 = new String("hi");  
    }  
}

需要注意的是,使用字面量创建的字符串,字符串会存储到内存的字符串常量池中。在Java有所谓"享元模式"(共享元素),即两个变量如果引用相同的字符串内容,系统会指向同一个字符串常量池中内的字符串。证明如下:

java 复制代码
public class Demo0 {  
    public static void main(String[] args) {  
        // 用字面量创建一个String对象  
        String s1 = "hello";  
        // 用字面量创建另外一个String对象,字符串内容完全相同  
        String s2 = "hello";  
        // 证明两个变量都是同一个对象的引用  
        System.out.println(s1 == s2); //  true  
    }  
}

而如果不是用的字面量,是用new创建两个String对象,则是完全不同的结果。用new创建两个字符串内容完全相同的String对象,会在内存堆里存储对象。两个变量则是完全不同的对象。证明如下:

java 复制代码
public class Demo1 {  
    public static void main(String[] args) {  
        // 用new创建一个String对象  
        String s1 = new String("hello");  
        // 用new创建另外一个String对象,字符串内容完全相同  
        String s2 = new String("hello");  
        // 证明两个变量是两个对象  
        System.out.println(s1 == s2); //  false  
    }  
}

字符串在编程中,是最常见的几种对象,因此String方法非常非常丰富。String对象是不可变的,其方法产生的字符串,都是返回一个新的String对象。

String常用的方法

String类的常见方法可以划分为基本操作、转换操作、替换与去除、截取与分隔、判断操作等分类。

String类的基本操作方法有:获取字符串长度、返回字符在字符串中第一次、最后一次出现的索引、返回字符串索引上的字符等。

java 复制代码
public class Demo2 {  
    public static void main(String[] args) {  
        String s1 = "hello";  
        // 获取字符串的长度  
        System.out.println(s1.length()); // 5  
        // 返回字符在字符串中第一次出现的索引  
        System.out.println(s1.indexOf('l')); // 2 (索引从0开始)  
        // 返回字符在字符串中最后一次出现的索引  
        System.out.println(s1.lastIndexOf('l')); // 3  
        // 返回指定索引的字符  
        System.out.println(s1.charAt(1)); // e  
    }  
}

String类的转换操作有:将字符串转换为字符数组、将int类型转换为字符串、将字符串中所有字符转换为小写、将字符串中所有字符转换为大写

java 复制代码
public class Demo3 {  
    public static void main(String[] args) {  
        String s1 = "hello";  
        // 将字符串转换为字符数组  
        char[] chs = s1.toCharArray();  
        for (int i = 0; i < chs.length; i++) {  
            System.out.print(chs[i]); // hello  
        }  
        System.out.println();  
        // 将int类型转换为字符串  
        int a = 10086;  
        String s2 = String.valueOf(a);  
        System.out.println(s2); // 10086  
        // 将字符串中的字符全部转换为大写  
        String s3 = s1.toUpperCase();  
        System.out.println(s3); // HELLO  
        // 将字符串中的字符全部转换为小写  
        String s4 = s1.toLowerCase();  
        System.out.println(s4); // hello  
    }  
}

String类的替换去除操作:用新字符串替换原有字符串,得到一个新的字符串;去除字符串首尾的空格。

java 复制代码
public class Demo4 {  
    public static void main(String[] args) {  
        String s1 = "hello";  
        // 用新字符串替换原有字符串,得到一个新的字符串  
        String s2 = s1.replace("hello", "helloworld");  
        System.out.println(s2); // helloworld  
        // 去除字符串首尾的空格  
        String s3 = "  hello  ";  
        String s4 = s3.trim();  // 建议用strip()替代
        System.out.println(s4); // hello  
    }  
}

需要注意:trim()只能去除ASCII码≤32 的空白字符(空格、制表符、换行等),但不能去除全角空格或其他Unicode空白字符。Java 11+引入了strip()方法来解决这个问题。因此,建议使用strip()方法替代trim()方法

String类的截取与分隔操作有:根据参数将原字符串分隔为若干个字符串(字符串数组)、截取从指定索引后的所有字符、截取从指定开始索引到指定结束索引之间的字符。

java 复制代码
public class Demo5 {  
    public static void main(String[] args) {  
        String s1 = "this is a text";  
        // 将原字符串分隔为若干个字符串(字符串数组)  
        String[] arr = s1.split(" ");  
        for (int i = 0; i < arr.length; i++) {  
            System.out.println(arr[i]);  
        }  
        // 截取从指定索引后的所有字符  
        String s2 = "helloworld";  
        System.out.println(s2.substring(5)); // world  
        // 截取从指定开始索引到指定结束索引之间的字符  
        System.out.println(s2.substring(2, 4)); // ll  
    }  
}

String类的判断操作有:判断与指定字符串比较是否相等、判断字符串是否以指定字符串开始、判断字符串是否以指定字符串结尾、判断字符串是否包含指定的字符序列、判断字符串是否为空(字符串长度为0)。

java 复制代码
public class Demo6 {  
    public static void main(String[] args) {  
        String s1 = "hello";  
        // 判断与指定字符串比较是否相等  
        System.out.println(s1.equals("hello")); // true  
        // 判断字符串是否以指定字符串开始  
        System.out.println(s1.startsWith("he")); // true  
        // 判断字符串是否以指定字符串结尾  
        System.out.println(s1.endsWith("lo")); // true  
        // 判断字符串是否包含指定的字符序列  
        System.out.println(s1.contains("llo")); // true  
        // 判断字符串是否为空  
        System.out.println(s1.isEmpty()); // false  
    }  
}

StringBuilder和StringBuffer类

由于String对象是不可变对象,因此String类的所有方法若是返回字符串,都是返回一个新的字符串。由于字符串是高频出现的对象,而因为字符串的不可变特性,对内存的开销较大。

因此,Java系统前后推出了StringBuffer类和StringBuilder类,作为String类的补充。两者都是可变的字符串对象,两者的方法都几乎相同,都是在原字符串上进行变更修改,而不是产生一个新的字符串对象。

以StringBuilder为例,演示StringBuilder和StringBuffer类的常用方法。

java 复制代码
public class Demo7 {  
    public static void main(String[] args) {  
        StringBuffer str = new StringBuffer("hello");  
        // append方法:添加字符串  
        str.append(" world");  
        System.out.println(str); // hello world  
        // insert方法:在指定位置添加字符串  
        str.insert(5, " java's");  
        System.out.println(str); // hello java's world  
        // replace方法:替换字符串  
        str.replace(5, 12, " java");  
        System.out.println(str); // hello java world  
        // delete方法:删除字符串  
        str.delete(5, 10);  
        System.out.println(str); // hello world  
    }  
}

StringBuffer类和StringBuilder类区别在于相对运行快慢和线程安全性,StringBuffer是线程安全的,运行性能比StringBuilder慢。而StringBuilder虽然是线程不安全的,但是优势在于运行速度快。

java 复制代码
package string.demo2;  
  
public class Demo7 {  
    public static void main(String[] args) {  
        StringBuffer str0 = new StringBuffer("hello");  
        StringBuilder str1 = new StringBuilder("hello");  
  
        // 测试StringBuffer对象方法的运行时间  
        long start = System.nanoTime();  
        // append方法:添加字符串  
        str0.append(" world");  
        System.out.println(str0); // hello world  
        // insert方法:在指定位置添加字符串  
        str0.insert(5, " java's");  
        System.out.println(str0); // hello java's world  
        // replace方法:替换字符串  
        str0.replace(5, 12, " java");  
        System.out.println(str0); // hello java world  
        // delete方法:删除字符串  
        str0.delete(5, 10);  
        System.out.println(str0); // hello world  
        long end = System.nanoTime();  
        System.out.println("StringBuffer运行时间:" + (end - start) + "纳秒");  
  
        System.out.println("------------------------------------------------");  
  
        // 测试StringBuilder对象方法的运行时间  
        long start1 = System.nanoTime();  
        str1.append(" world");  
        System.out.println(str1);  
        str1.insert(5, " java's");  
        System.out.println(str1);  
        str1.replace(5, 12, " java");  
        System.out.println(str1);  
        str1.delete(5, 10);  
        System.out.println(str1);  
        long end1 = System.nanoTime();  
        System.out.println("StringBuilder运行时间:" + (end1 - start1) + "纳秒");  
    }  
}
shell 复制代码
hello world
hello java's world
hello java world
hello world
StringBuffer运行时间:398609纳秒
------------------------------------------------
hello world
hello java's world
hello java world
hello world
StringBuilder运行时间:92160纳秒

进程已结束,退出代码为 0

由此可见,StringBuilder确实要更快一些。一般情况下,我们都是单线程运行程序,因此推荐用StringBuilder。

相关推荐
低保和光头哪个先来2 小时前
场景6:对浏览器内核的理解
开发语言·前端·javascript·vue.js·前端框架
小北方城市网2 小时前
Python + 前后端全栈进阶课程(共 10 节|完整版递进式|从技术深化→项目落地→就业进阶,无缝衔接基础课)
大数据·开发语言·网络·python·数据库架构
程序员JerrySUN2 小时前
OP-TEE + YOLOv8:从“加密权重”到“内存中解密并推理”的完整实战记录
android·java·开发语言·redis·yolo·架构
阿里嘎多学长2 小时前
2025-12-30 GitHub 热点项目精选
开发语言·程序员·github·代码托管
BullSmall2 小时前
Doris的备份及恢复方案
学习
+VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vueOA工程项目管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
小李子不吃李子2 小时前
人工智能与创新第二章练习题
人工智能·学习
不会学习?2 小时前
大二元旦,2025最后一天
经验分享·笔记
郝学胜-神的一滴3 小时前
Linux进程与线程控制原语对比:双刃出鞘,各显锋芒
linux·服务器·开发语言·数据结构·c++·程序人生