news 2026/6/19 12:48:49

Java字符串全解:从String到StringTokenizer,期末复习与实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java字符串全解:从String到StringTokenizer,期末复习与实战指南

9.1 字符串概述

在Java编程中,字符串(String)是使用最频繁的数据类型之一,它代表一个不可变的字符序列。本章将系统性地梳理Java字符串相关的核心类:StringStringBuilderStringBuffer以及一个较老的字符串分割工具StringTokenizer。理解它们的特性和适用场景,不仅是期末考试的重要考点,更是日后项目开发的实操基础。

学习目标

  • 掌握String的创建、不可变性及其影响。
  • 理解StringBuilderStringBuffer的可变性及适用场景。
  • 学会使用StringTokenizer进行字符串分割。
  • 能够根据实际需求(如性能、线程安全)选择合适的字符串类。

9.2 String(创建+使用)

String类是java.lang包下的核心类,用于创建和操作不可变的字符串。

9.2.1 创建String对象的两种方式

创建String对象主要有两种方式:直接赋值和使用new关键字。

1. 直接赋值

Strings1="Hello";Strings2="Hello";

运行输出分析
s1 == s2的结果为true。这是因为字符串字面量"Hello"被存储在字符串常量池中。s1s2指向的是常量池中的同一个对象,所以引用地址相同。

2. 使用new关键字

Strings3=newString("Hello");Strings4=newString("Hello");

运行输出分析
s3 == s4的结果为falsenew关键字会在堆内存中创建一个新的String对象,即使内容相同,s3s4也是两个不同的对象,引用地址不同。
s3.equals(s4)的结果为true,因为equals方法比较的是字符串的内容。

9.2.2 String类的常用方法

String提供了丰富的方法来操作字符串,以下是一些核心方法及其测试代码:

publicclassStringDemo{publicstaticvoidmain(String[]args){Stringstr=" Java Programming ";// 1. 获取长度System.out.println("长度: "+str.length());// 输出: 长度: 20// 2. 去除首尾空格Stringtrimmed=str.trim();System.out.println("去除空格后: \""+trimmed+"\"");// 输出: 去除空格后: "Java Programming"// 3. 获取子字符串Stringsub=str.substring(5,16);// 索引从0开始,[5,16)System.out.println("子串: "+sub);// 输出: 子串: Programming// 4. 查找字符/字符串位置intindex=str.indexOf("Pro");System.out.println("\"Pro\"的索引: "+index);// 输出: "Pro"的索引: 7// 5. 字符串替换Stringreplaced=str.replace("Java","Python");System.out.println("替换后: "+replaced);// 输出: 替换后: Python Programming// 6. 大小写转换System.out.println("大写: "+str.toUpperCase());// 输出: 大写: JAVA PROGRAMMINGSystem.out.println("小写: "+str.toLowerCase());// 输出: 小写: java programming// 7. 分割字符串Stringcsv="Apple,Banana,Orange";String[]fruits=csv.split(",");System.out.println("分割后第一个水果: "+fruits[0]);// 输出: 分割后第一个水果: Apple}}

考点提示:牢记substring是前闭后开区间[beginIndex, endIndex)indexOf找不到返回-1

9.3 StringBuilder(创建+使用)

StringBuilder代表一个可变的字符序列。当需要频繁修改字符串内容(如拼接、插入、删除)时,使用StringBuilderString性能高得多,因为它避免了创建大量临时String对象。

9.3.1 创建与基本使用

publicclassStringBuilderDemo{publicstaticvoidmain(String[]args){// 1. 创建StringBuildersb1=newStringBuilder();// 默认容量16StringBuildersb2=newStringBuilder("Hello");// 指定初始内容StringBuildersb3=newStringBuilder(50);// 指定初始容量// 2. 追加内容sb1.append("Java");sb1.append(" ");sb1.append(17);// 可以追加任何类型,自动转为字符串System.out.println("追加后: "+sb1.toString());// 输出: 追加后: Java 17// 3. 插入内容sb2.insert(5," World");System.out.println("插入后: "+sb2);// 输出: 插入后: Hello World// 4. 删除内容sb2.delete(5,11);// 删除[5,11)位置的字符System.out.println("删除后: "+sb2);// 输出: 删除后: Hello// 5. 替换内容sb2.replace(0,5,"Hi");System.out.println("替换后: "+sb2);// 输出: 替换后: Hi// 6. 反转字符串sb2.reverse();System.out.println("反转后: "+sb2);// 输出: 反转后: iH}}

实操重点:在单线程环境下进行大量字符串修改操作,StringBuilder是首选。

9.4 StringBuffer

StringBufferStringBuilder在功能上几乎完全相同,都代表可变的字符序列。它们的关键区别在于线程安全性

9.4.1 核心特性与使用

StringBuffer的方法是同步的(synchronized),因此是线程安全的。这意味着多个线程可以安全地同时操作同一个StringBuffer对象。而StringBuilder的方法是非同步的,线程不安全,但在单线程环境下性能更高。

publicclassStringBufferDemo{publicstaticvoidmain(String[]args){StringBuffersbf=newStringBuffer("ThreadSafe");// 方法与StringBuilder类似sbf.append(" Buffer");System.out.println(sbf);// 输出: ThreadSafe Buffersbf.insert(10,"-");System.out.println(sbf);// 输出: ThreadSafe- Buffer}}

考点与选择策略

  • 考点StringBuffervsStringBuilder的核心区别是线程安全性。
  • 实操:绝大多数现代应用都是单线程操作字符串,因此优先使用StringBuilder。只有在明确涉及多线程共享并修改同一个字符串对象时,才考虑使用StringBuffer

9.5 StringTokenizer

StringTokenizer是一个用于分割字符串的遗留类(Legacy Class),位于java.util包。虽然现在更推荐使用Stringsplit()方法或正则表达式,但理解它仍有必要,尤其是在处理一些简单分隔符或考试中。

9.5.1 基本用法

importjava.util.StringTokenizer;publicclassStringTokenizerDemo{publicstaticvoidmain(String[]args){Stringdata="Java,Python,JavaScript,C++";// 默认分隔符为空格、制表符、换行符等// 此处指定逗号为分隔符StringTokenizerst=newStringTokenizer(data,",");System.out.println("令牌数量: "+st.countTokens());// 输出: 令牌数量: 4// 遍历所有令牌while(st.hasMoreTokens()){System.out.println(st.nextToken());}// 输出:// Java// Python// JavaScript// C++}}

9.5.2 StringTokenizer vs String.split()

特性StringTokenizerString.split() (基于正则表达式)
所属包java.util(遗留类)java.lang.String
功能仅按分隔符拆分按正则表达式拆分,功能强大
空令牌处理默认忽略空字符串默认保留空字符串(除非使用限定符)
性能对于简单分隔符,性能稍好正则表达式编译有开销,但功能更灵活
推荐度不推荐在新代码中使用推荐使用,功能全面,API现代

实操建议:除非在处理性能极其敏感且分隔规则极其简单的场景,否则一律使用String.split()java.util.regex.Pattern

对比与总结

对比表格1:String直接赋值 vs new String()

对比项直接赋值 (String s = “abc”)new String(“abc”)
内存区域字符串常量池堆内存
对象数量常量池中只有一个对象,所有相同字面量共享每次new都会在堆中创建一个新对象
==比较相同字面量比较为true即使内容相同,比较也为false
适用场景推荐,节省内存需要明确创建独立对象时

对比表格2:三大字符串类核心差异

特性StringStringBuilderStringBuffer
可变性不可变 (Immutable)可变 (Mutable)可变 (Mutable)
线程安全是(因为不可变)(方法同步)
性能修改性能差(创建新对象)(单线程)较低(因同步开销)
使用场景存储不变字符串、作为键单线程下频繁修改字符串多线程下共享修改字符串
诞生版本Java 1.0Java 5Java 1.0

易错考点整理

1. 常量池陷阱

Strings1="Hello";Strings2="Hello";Strings3=newString("Hello");Strings4=s3.intern();// 将s3指向的对象放入常量池,并返回常量池引用System.out.println(s1==s2);// trueSystem.out.println(s1==s3);// falseSystem.out.println(s1==s4);// true (intern后)

考点:理解==比较引用,equals比较内容。intern()方法可以主动将字符串对象放入常量池。

2. 循环拼接性能问题

错误示范(性能极差)

Stringresult="";for(inti=0;i<10000;i++){result+=i;// 每次循环都创建新的String对象和StringBuilder对象!}

正确做法(使用StringBuilder)

StringBuildersb=newStringBuilder();for(inti=0;i<10000;i++){sb.append(i);}Stringresult=sb.toString();

3. 线程安全问题

  • String:线程安全(不可变)。
  • StringBuilder非线程安全。多线程操作同一对象需自行加锁。
  • StringBuffer:线程安全(内部同步),但性能有损耗。

复习思考题

  1. 基础概念String类的不可变性指的是什么?这种设计带来了哪些优点和缺点?
  2. 代码分析:以下代码会创建几个String对象?
    Strings1="abc";Strings2=newString("abc");Strings3=s2.intern();
  3. 性能选择:在一个单线程的Web服务器中,需要动态生成一个很长的HTML字符串,应该选择StringStringBuilder还是StringBuffer?为什么?
  4. 方法辨析Stringsplit()方法和StringTokenizer在分割字符串“a,b,c”(以逗号分隔)时,输出结果有何不同?
  5. 实战应用:如何判断一个字符串是否为回文字符串(正读反读都一样)?请用StringBuilderStringBuffer实现。

本文涵盖了Java字符串章节的核心知识点、代码示例与易错点,适合作为期末复习笔记。建议读者亲手运行所有示例代码,并结合思考题进行巩固,祝大家考试顺利!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/19 12:44:00

Gemma 4深度解析:Apache 2.0开源大模型的数学推理架构与工程落地

1. 项目概述&#xff1a;为什么Gemma 4的发布让一线模型工程师集体点开GitHub “Gemma 4”这个名称在2024年中旬突然出现在Hugging Face模型库首页时&#xff0c;我正调试一个被客户反复卡在数学推理环节的金融问答服务。当时第一反应不是点开链接&#xff0c;而是下意识去翻Ap…

作者头像 李华
网站建设 2026/6/19 12:33:23

vLLM v0.19.0深度解析:CPU KV缓存卸载与多模态推理优化

1. 这不是一次普通升级&#xff1a;vLLM v0.19.0 的真实分量在哪里vLLM v0.19.0 发布当天&#xff0c;我正在调试一个部署在边缘服务器上的多模态问答服务&#xff0c;内存频繁告警&#xff0c;KV缓存占满85%以上&#xff0c;推理延迟波动超过300ms。刷新GitHub Release页面看到…

作者头像 李华
网站建设 2026/6/19 12:30:10

SPI协议深度解析:从CPHA/CPOL时序到OVRF/MODF错误处理实战

1. 项目概述&#xff1a;从芯片手册到实战经验如果你在嵌入式开发中用过SPI&#xff0c;大概率对它的“简单”又爱又恨。爱的是它接线少、协议直观&#xff0c;恨的是手册里那些关于CPHA、CPOL、错误标志和中断的细节&#xff0c;稍不留神就会让通信彻底“哑火”。我手边正好有…

作者头像 李华
网站建设 2026/6/19 12:18:50

NXP FS6407/FS6408 SBC的16位SPI接口深度解析与安全驱动实践

1. 项目概述与核心价值 在汽车电子和工业控制领域&#xff0c;系统的基础供电、监控与通信的可靠性是设计的生命线。NXP的FS6407/FS6408系列电源系统基础芯片&#xff08;SBC&#xff09;正是为此类高要求应用而生的核心器件。它集成了多路电源轨、看门狗、唤醒管理、故障诊断以…

作者头像 李华
网站建设 2026/6/19 12:16:50

从NFA到DFA:用Python与Graphviz可视化子集构造法

1. 理解NFA与DFA的基础概念 非确定有限自动机&#xff08;NFA&#xff09;和确定有限自动机&#xff08;DFA&#xff09;是编译原理中两种重要的自动机模型。NFA允许一个状态在接收同一个输入字符时转移到多个可能的状态&#xff0c;这种不确定性使得NFA在理论描述上更为灵活。…

作者头像 李华