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。

相关推荐
REDcker25 分钟前
浏览器端Web程序性能分析与优化实战 DevTools指标与工程清单
开发语言·前端·javascript·vue·ecmascript·php·js
努力努力再努力FFF1 小时前
医生对AI辅助诊断感兴趣,作为临床人员该怎么了解和学习?
人工智能·学习
OBiO20131 小时前
Cell | 突破AAV载体容量限制!路中华/姜玉武/刘太安团队开发AAVLINK系统实现大基因递送
笔记
极客先躯2 小时前
高级java每日一道面试题-2025年11月24日-容器与虚拟化题[Dockerj]-runc 的作用是什么?
java·oci 的命令行工具·最小可用·无守护进程·完全标准·创建容器的核心流程·runc 核心职责思维导图
用户60648767188962 小时前
AI 抢不走的技能:用 Claude API 构建自动化工作流实战
java
我命由我123452 小时前
Kotlin 开发 - lateinit 关键字
android·java·开发语言·kotlin·android studio·android-studio·android runtime
aXin_ya2 小时前
微服务第八天 Sentinel 四种分布式事务模式
java·数据库·微服务
智者知已应修善业2 小时前
【51单片机2个按键控制流水灯运行与暂停】2023-9-6
c++·经验分享·笔记·算法·51单片机
Halo_tjn2 小时前
Java Set集合相关知识点
java·开发语言·算法
Linsk2 小时前
Java和JavaScript的关系真是雷峰和雷峰塔的关系吗?
java·javascript·oracle