1 字符串概述(字符串常量)
String str = "abc";
String str1=new String("abc");
字符串是类,是引用的数据类型

2 字符串的常量
String str = "abc";
str="abcd";
这是定义了一个字符串的常量。常量是不可改变的量,字符串是不能改变的。
java
public class StringDemo {
public static void main(String[] args) {
//定义一个字符类型的常量,这个常量是个对象"ren",字符串的常量需要使用""来引起来
String str = "shi";
str = str + "zhaoyang";
System.out.println(str); // shizhaoyang,返回的是一个新的字符串
}
}
字符串常量的内存结构
java
public class StringTest {
public static void main(String[] args) {
String str = "abc";
String str1 = "abc";
System.out.println(str == str1); 返回结果为 true,都从静态常量池中取出内存地址的路径返回给变量
}
}


java
public class StringTest {
public static void main(String[] args) {
String str = "shi";
str += "zhaoyang";
System.out.println(str);
}
}
1.字符串常量是共享的
2.字符串不能变化,如果我们在字符串上做拼接,其实是新产生一个字符串。
1、字符串为什么不可变
<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">String</font> 类的定义如下:
java
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
private final char[] value;
}
<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">public final class String</font>:<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">String</font>类本身是<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">final</font>的,意味着它不能被继承,防止子类修改其行为。<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">private final char[] value;</font>:<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">value</font>数组存储了字符串的字符内容,且被<font style="color:rgb(25, 27, 31);background-color:rgb(248, 248, 250);">final</font>修饰,使得其引用不能被修改。
2、String、StringBuilder、StringBuffer 区别
总结:
- 1、运行速度:StringBuilder运行速度最快,StringBuffer运行速度稍慢,String运行速度最慢。
- 2、线程安全性:StringBuffer多线程安全,StringBuilder和String单线程安全
- 3、适用情况:StringBuilder适用于单线程下字符串大量操作,StringBuffer适用于多线程下的字符串大量操作,String适用于少量字符串操作的情况。
String、StringBuilder、StringBuffer的核心区别如下:
| 特性 | String | StringBuilder | StringBuffer |
|---|---|---|---|
| 可变性 | ❌ 不可变 | ✅ 可变 | ✅ 可变 |
| 线程安全 | ✅ 线程安全 | ❌ 非线程安全 | ✅ 线程安全 |
| 性能 | 最慢(频繁创建对象) | 最快(无同步开销) | 较慢(有同步开销) |
| 内存效率 | 最低(频繁分配新内存) | 最高(原地修改) | 较高(原地修改) |
| 使用场景 | 字符串常量、配置、键值 | 单线程字符串拼接 | 多线程字符串操作 |
| 继承关系 | Object→String | Object→AbstractStringBuilder→StringBuilder | Object→AbstractStringBuilder→StringBuffer |
| Java版本 | 1.0 | 1.5 | 1.0 |
1. String的适用场景
适用于不需要被大量修改的场景当中,保持String不可变的特性。
java
public class StringUseCases {
// 1. 常量字符串(最佳场景)
public static final String DATABASE_URL = "jdbc:mysql://localhost:3306/test";
public static final String APP_NAME = "MyApplication";
// 2. Map的键(因为不可变,hashCode稳定)
public void mapKeyExample() {
Map<String, String> config = new HashMap<>();
config.put("server.host", "localhost");
config.put("server.port", "8080");
// 由于String不可变,作为key是安全的
String key = "server.host";
config.get(key); // 始终能正确找到
}
// 3. 线程间共享(天然线程安全)
class SharedResource {
// 多个线程可以安全地读取这个String
private final String sharedConfig = "config_value";
public void process() {
// 线程安全,无需同步
System.out.println(sharedConfig);
}
}
// 4. 类名、方法名等标识符
public void reflectionExample() throws Exception {
String className = "java.lang.String";
Class<?> clazz = Class.forName(className); // 类名不可变很重要
String methodName = "length";
Method method = clazz.getMethod(methodName); // 方法名不可变很重要
}
// 5. 配置文件值
@Value("${app.name}") // Spring注入
private String appName;
}
2、StringBuilder(可变字符串,非线程安全)
扩容机制:变为原来长度的2倍或者进行手动扩容。
java
public class StringBuilderDeepDive {
public static void main(String[] args) {
// 1. 基本使用 - 可变性
StringBuilder sb = new StringBuilder();
System.out.println("初始容量: " + sb.capacity()); // 默认16
// 追加操作 - 原地修改
sb.append("Hello");
sb.append(" ");
sb.append("World");
System.out.println("内容: " + sb.toString()); // Hello World
System.out.println("长度: " + sb.length()); // 11
System.out.println("容量: " + sb.capacity()); // 16(还够用)
// 2. 链式调用(流畅接口设计)
StringBuilder sb2 = new StringBuilder()
.append("Java")
.append(" ")
.append("is")
.append(" ")
.append("awesome")
.insert(0, "I think ") // 插入
.delete(0, 2) // 删除
.reverse(); // 反转
System.out.println("\n链式操作结果: " + sb2);
// 3. 容量管理和扩容机制
capacityManagementDemo();
// 4. 性能对比演示
performanceComparison();
// 5. 线程不安全演示
threadSafetyIssueDemo();
}
static void capacityManagementDemo() {
System.out.println("\n=== 容量管理演示 ===");
// 初始容量16
StringBuilder sb = new StringBuilder();
System.out.println("初始: 长度=" + sb.length() + ", 容量=" + sb.capacity());
// 添加17个字符,触发扩容
sb.append("12345678901234567"); // 17个字符
System.out.println("添加17字符后: 长度=" + sb.length() + ", 容量=" + sb.capacity());
// 容量变为:原容量(16)*2 + 2 = 34
// 继续添加,再次扩容
sb.append("89012345678901234567890"); // 再加23个
System.out.println("再加23字符后: 长度=" + sb.length() + ", 容量=" + sb.capacity());
// 容量变为:所需容量(40) > 当前容量(34),所以扩容到40
// 手动扩容
sb.ensureCapacity(100);
System.out.println("ensureCapacity(100)后: 容量=" + sb.capacity());
// 压缩到实际大小
sb.trimToSize();
System.out.println("trimToSize()后: 长度=" + sb.length() + ", 容量=" + sb.capacity());
}
static void performanceComparison() {
System.out.println("\n=== 性能对比演示 ===");
int iterations = 100000;
// String拼接
long start = System.nanoTime();
String strResult = "";
for (int i = 0; i < iterations; i++) {
strResult += "a"; // 每次创建新对象
}
long stringTime = System.nanoTime() - start;
// StringBuilder拼接
start = System.nanoTime();
StringBuilder sbResult = new StringBuilder();
for (int i = 0; i < iterations; i++) {
sbResult.append("a"); // 原地修改
}
String sbFinal = sbResult.toString();
long sbTime = System.nanoTime() - start;
System.out.println("循环" + iterations + "次拼接:");
System.out.printf("String: %.2f ms\n", stringTime / 1_000_000.0);
System.out.printf("StringBuilder: %.2f ms\n", sbTime / 1_000_000.0);
System.out.printf("StringBuilder快 %.1f 倍\n",
(double)stringTime / sbTime);
}
static void threadSafetyIssueDemo() {
System.out.println("\n=== 线程安全问题演示 ===");
final StringBuilder unsafeBuilder = new StringBuilder();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
unsafeBuilder.append(Thread.currentThread().getName())
.append("-").append(i).append(" ");
}
};
Thread t1 = new Thread(task, "T1");
Thread t2 = new Thread(task, "T2");
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 可能出现的问题:
// 1. 数据丢失(部分append没生效)
// 2. 数据损坏(字符错乱)
// 3. 数组越界异常
System.out.println("StringBuilder多线程操作可能存在问题");
System.out.println("实际长度: " + unsafeBuilder.length());
// 理想应该是 2*1000*(线程名长度 + 数字长度 + 2) ≈ 26000
// 但实际可能小于这个值(数据丢失)
}
}
2. 源码分析
java
// StringBuilder关键源码分析
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence {
// 构造方法
public StringBuilder() {
super(16); // 默认容量16
}
public StringBuilder(int capacity) {
super(capacity); // 指定容量
}
public StringBuilder(String str) {
super(str.length() + 16); // 容量 = 字符串长度 + 16
append(str);
}
// 关键:所有修改方法都没有 synchronized!
@Override
public StringBuilder append(String str) {
super.append(str); // 调用父类方法
return this; // 返回自身,支持链式调用
}
// 其他方法类似,都没有同步
}
// 父类 AbstractStringBuilder
abstract class AbstractStringBuilder implements Appendable, CharSequence {
// 内部字符数组 - 不是final的!
char[] value;
// 当前长度
int count;
// append方法实现
public AbstractStringBuilder append(String str) {
if (str == null) {
return appendNull(); // 处理null
}
int len = str.length();
// 确保容量足够
ensureCapacityInternal(count + len);
// 复制数据到内部数组
str.getChars(0, len, value, count);
count += len; // 更新长度
return this;
}
// 扩容机制
private void ensureCapacityInternal(int minimumCapacity) {
// 如果所需容量 > 当前容量,进行扩容
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity)); // 创建新数组并复制数据
}
}
// 新容量计算策略
private int newCapacity(int minCapacity) {
// 新容量 = 原容量 * 2 + 2
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity; // 如果还不够,直接用所需容量
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
}
3. StringBuilder适用场景
java
public class StringBuilderUseCases {
// 1. 大量字符串拼接(最佳场景)
public String buildSQL(String table, Map<String, Object> conditions) {
StringBuilder sql = new StringBuilder("SELECT * FROM ")
.append(table)
.append(" WHERE 1=1");
for (Map.Entry<String, Object> entry : conditions.entrySet()) {
sql.append(" AND ")
.append(entry.getKey())
.append(" = '")
.append(entry.getValue())
.append("'");
}
return sql.toString();
}
// 2. 构建JSON/XML字符串
public String buildJSON(List<User> users) {
StringBuilder json = new StringBuilder("[");
for (int i = 0; i < users.size(); i++) {
User user = users.get(i);
json.append("{")
.append("\"id\":").append(user.getId()).append(",")
.append("\"name\":\"").append(user.getName()).append("\",")
.append("\"email\":\"").append(user.getEmail()).append("\"")
.append("}");
if (i < users.size() - 1) {
json.append(",");
}
}
json.append("]");
return json.toString();
}
// 3. 日志消息构建
public void logRequest(HttpServletRequest request) {
StringBuilder log = new StringBuilder()
.append("[REQUEST] ")
.append("method=").append(request.getMethod()).append(", ")
.append("path=").append(request.getRequestURI()).append(", ")
.append("client=").append(request.getRemoteAddr());
System.out.println(log.toString());
}
// 4. 动态SQL/查询条件构建
public String buildDynamicQuery(String baseQuery, SearchCriteria criteria) {
StringBuilder query = new StringBuilder(baseQuery);
boolean firstCondition = true;
if (criteria.getName() != null) {
query.append(firstCondition ? " WHERE " : " AND ")
.append("name LIKE '%").append(criteria.getName()).append("%'");
firstCondition = false;
}
if (criteria.getMinAge() != null) {
query.append(firstCondition ? " WHERE " : " AND ")
.append("age >= ").append(criteria.getMinAge());
firstCondition = false;
}
return query.toString();
}
}
3、StringBuffer(可变字符串,线程安全)
java
public class StringBufferDeepDive {
public static void main(String[] args) throws InterruptedException {
// 1. 基本使用(API与StringBuilder几乎相同)
StringBuffer buffer = new StringBuffer();
buffer.append("Hello").append(" ").append("World");
System.out.println("StringBuffer: " + buffer);
// 2. 线程安全性演示
threadSafetyDemo();
// 3. 性能对比
performanceDemo();
// 4. 源码分析
sourceCodeAnalysis();
}
static void threadSafetyDemo() throws InterruptedException {
System.out.println("\n=== 线程安全性演示 ===");
final StringBuffer safeBuffer = new StringBuffer();
final StringBuilder unsafeBuilder = new StringBuilder();
int threadCount = 10;
int iterations = 1000;
// 创建线程数组
Thread[] threads = new Thread[threadCount];
// 测试StringBuffer
long start = System.nanoTime();
for (int i = 0; i < threadCount; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < iterations; j++) {
safeBuffer.append("a");
}
});
threads[i].start();
}
// 等待所有线程完成
for (Thread t : threads) {
t.join();
}
long bufferTime = System.nanoTime() - start;
System.out.println("StringBuffer 多线程结果:");
System.out.println("期望长度: " + (threadCount * iterations));
System.out.println("实际长度: " + safeBuffer.length());
System.out.println("数据是否正确: " +
(safeBuffer.length() == threadCount * iterations));
// 测试StringBuilder(对比)
start = System.nanoTime();
for (int i = 0; i < threadCount; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < iterations; j++) {
unsafeBuilder.append("a");
}
});
threads[i].start();
}
for (Thread t : threads) {
t.join();
}
long builderTime = System.nanoTime() - start;
System.out.println("\nStringBuilder 多线程结果:");
System.out.println("期望长度: " + (threadCount * iterations));
System.out.println("实际长度: " + unsafeBuilder.length());
System.out.println("数据可能不正确: " +
(unsafeBuilder.length() != threadCount * iterations));
System.out.println("\n多线程性能对比:");
System.out.printf("StringBuffer耗时: %.2f ms\n", bufferTime / 1_000_000.0);
System.out.printf("StringBuilder耗时: %.2f ms\n", builderTime / 1_000_000.0);
System.out.println("注意:StringBuilder数据可能不正确,但看起来更快");
}
static void performanceDemo() {
System.out.println("\n=== 单线程性能演示 ===");
int iterations = 1000000;
// StringBuffer测试
long start = System.nanoTime();
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < iterations; i++) {
buffer.append("test");
}
String bufferResult = buffer.toString();
long bufferTime = System.nanoTime() - start;
// StringBuilder测试
start = System.nanoTime();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < iterations; i++) {
builder.append("test");
}
String builderResult = builder.toString();
long builderTime = System.nanoTime() - start;
System.out.println("单线程" + iterations + "次append:");
System.out.printf("StringBuffer: %.2f ms\n", bufferTime / 1_000_000.0);
System.out.printf("StringBuilder: %.2f ms\n", builderTime / 1_000_000.0);
System.out.printf("StringBuilder快 %.1f%%\n",
(bufferTime - builderTime) * 100.0 / bufferTime);
}
static void sourceCodeAnalysis() {
System.out.println("\n=== 源码关键区别 ===");
System.out.println("StringBuffer关键方法都有 synchronized:");
System.out.println("public synchronized StringBuffer append(String str) {");
System.out.println(" toStringCache = null;");
System.out.println(" super.append(str);");
System.out.println(" return this;");
System.out.println("}");
System.out.println("\nStringBuilder方法没有 synchronized:");
System.out.println("public StringBuilder append(String str) {");
System.out.println(" super.append(str);");
System.out.println(" return this;");
System.out.println("}");
System.out.println("\nStringBuffer的toString()也优化了缓存:");
System.out.println("private transient char[] toStringCache; // 缓存");
System.out.println("public synchronized String toString() {");
System.out.println(" if (toStringCache == null) {");
System.out.println(" toStringCache = Arrays.copyOfRange(value, 0, count);");
System.out.println(" }");
System.out.println(" return new String(toStringCache, true);");
System.out.println("}");
}
}
2. StringBuffer适用场景
java
public class StringBufferUseCases {
// 1. 多线程环境下的字符串操作
class ThreadSafeLogger {
private final StringBuffer logBuffer = new StringBuffer();
// 多个线程可以安全地追加日志
public synchronized void log(String message) {
logBuffer.append(Thread.currentThread().getName())
.append(": ")
.append(message)
.append("\n");
}
public String getLog() {
return logBuffer.toString();
}
}
// 2. Servlet环境(多线程)
public class ThreadSafeServlet extends HttpServlet {
// 实例变量,多个请求共享(需要线程安全)
private final StringBuffer sharedBuffer = new StringBuffer();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 多个线程可能同时访问
synchronized (sharedBuffer) {
sharedBuffer.append("Request from: ")
.append(req.getRemoteAddr())
.append("\n");
}
// 或者使用StringBuffer的同步方法
sharedBuffer.append("Request at: ")
.append(new Date())
.append("\n");
}
}
// 3. 全局缓存构建
public class GlobalCacheBuilder {
private static final StringBuffer cache = new StringBuffer();
private static final Object lock = new Object();
public static void addToCache(String data) {
// 方法1:使用StringBuffer的同步方法
cache.append(data);
// 方法2:或者使用外部同步(更细粒度控制)
synchronized (lock) {
cache.append(data);
// 其他需要同步的操作...
}
}
public static String getCache() {
return cache.toString();
}
}
// 4. 遗留系统维护(StringBuffer在Java 1.0就存在)
public class LegacySystemAdapter {
// 一些老代码可能还在用StringBuffer
public String processLegacyData(StringBuffer oldBuffer) {
// 与老代码交互
oldBuffer.append("[Processed]");
return oldBuffer.toString();
}
}
}
| 操作类型 | String | StringBuilder | StringBuffer | 说明 |
|---|---|---|---|---|
| 单线程拼接 | 非常慢 | 最快 | 较慢 | StringBuilder无同步开销 |
| 多线程拼接 | 非常慢 | 可能出错 | 安全但较慢 | StringBuffer有同步保证 |
| 内存占用 | 高 | 低 | 低 | String频繁创建新对象 |
| 创建对象数 | 非常多 | 最少 | 最少 | String每次操作都创建新对象 |
决策流程图:
plain
开始选择字符串类
↓
需要字符串常量吗?
├── 是 → 使用 String
└── 否 → 需要修改字符串吗?
├── 否 → 使用 String
└── 是 → 在什么线程环境下?
├── 单线程 → 使用 StringBuilder(性能最好)
└── 多线程 → 使用 StringBuffer(线程安全)
| 维度 | String | StringBuilder | StringBuffer |
|---|---|---|---|
| 可变性 | 不可变 | 可变 | 可变 |
| 线程安全 | 安全 | 不安全 | 安全 |
| 性能 | 最慢 | 最快 | 中等 |
| 内存 | 开销大 | 开销小 | 开销小 |
| 使用场景 | 常量、配置 | 单线程拼接 | 多线程拼接 |
| 版本 | JDK 1.0 | JDK 1.5 | JDK 1.0 |
| 同步 | 不需要 | 需要外部同步 | 内置同步 |
| 推荐使用 | 固定字符串 | 单线程操作 | 多线程操作 |
黄金法则:
- 固定不变 → String
- 单线程修改 → StringBuilder
- 多线程修改 → StringBuffer
- 简单连接 → String "+"
- 复杂构建 → StringBuilder/StringBuffer
3 字符串的构造器
字符串构造器创建字符串的形式大致分为三种,第一种接受byte[]数组,第二种接受char[]数组,第三种接受字符串
字符串常量是一种定义的方式 Strig str="abc"
字符串需要有其他形式的构造器,比如可以通过字符的数组,字节数组,io流中的数据等等 。


java
public class StringTest1 {
public static void main(String[] args) {
String s = new String();
System.out.println(s); // 返回结果为空串
String s1 = ""; // 返回结果也是空串
byte[] bs = {97,98,99,100};
//通过字节数组创建字符串
String s2 = new String(bs);
System.out.println(s2); // abcd,将数组中的数字转化为字符拼接起来
//通过字节数组创建字符串,offset就是索引的开始位置,length取的长度
String s3 = new String(bs, 1, 3); [] 的形式,左闭右闭
System.out.println(s3);
char[] cs = {'b','a','g','h','g'};
//通过字符的数组来创建一个字符串
String s4 = new String(cs);
System.out.println(cs);
//通过字符数组创建字符串,offset就是索引的开始位置,length取的长度
String s5 = new String(cs, 2, 2);
System.out.println(s5);
//通过字符串的常量创建字符串的对象
String s6 = new String("hello");
System.out.println(s6);
}
}
4.String s2 = "abc"和String s1 = new String ("abc")有什么区别?
new String ("abc");如果没有在字符串的常量池中没有abc就会在堆中创建一个对象,同时又在字符串常量池中也创建一个对象,然后用堆中的对象来引用字符串常量池中对象。实则创建了2个对象。
new String ("abc"); 如果在字符串的常量池中有abc,那么就会在堆中创建一个对象,直接引用已经存在的字符串常量池中的那个对象。

5.空字符串和null的区别
String str=null;
String str1=" ";

空字符串是有效的引用,有地址的,只不过是内容的长度是0
null这个引用是空引用,不能使用。使用一定会报空指针的错误。引用数据类型的默认值是null。
6.字符串中常用的方法
| 类别 | 方法 | 说明 | 版本 |
|---|---|---|---|
| 基础信息 | length() | 字符串长度 | 1.0 |
| isEmpty() | 是否空字符串 | 1.6 | |
| isBlank() | 是否空白 | 11 | |
| 比较 | equals() | 比较内容 | 1.0 |
| equalsIgnoreCase() | 忽略大小写比较 | 1.0 | |
| compareTo() | 字典顺序比较 | 1.0 | |
| compareToIgnoreCase() | 忽略大小写字典比较 | 1.0 | |
| contentEquals() | 与CharSequence比较 | 1.4 | |
| 查找 | indexOf() | 查找字符/字符串 | 1.0 |
| lastIndexOf() | 反向查找 | 1.0 | |
| contains() | 是否包含 | 1.5 | |
| startsWith() | 是否以...开头 | 1.0 | |
| endsWith() | 是否以...结尾 | 1.0 | |
| 提取 | charAt() | 获取字符 | 1.0 |
| substring() | 截取子串 | 1.0 | |
| subSequence() | 返回CharSequence | 1.4 | |
| 分割 | split() | 正则分割 | 1.4 |
| lines() | 返回行流 | 11 | |
| 转换 | toLowerCase() | 转小写 | 1.0 |
| toUpperCase() | 转大写 | 1.0 | |
| toCharArray() | 转字符数组 | 1.0 | |
| 空白处理 | trim() | 去除首尾空白 | 1.0 |
| strip() | Unicode空白处理 | 11 | |
| stripLeading() | 去除开头空白 | 11 | |
| stripTrailing() | 去除结尾空白 | 11 | |
| 替换 | replace() | 字符/字符串替换 | 1.0 |
| replaceAll() | 正则替换所有 | 1.4 | |
| replaceFirst() | 正则替换第一个 | 1.4 | |
| 格式化 | format() | 格式化字符串 | 1.5 |
| formatted() | 实例方法格式化 | 15 | |
| 编码 | getBytes() | 转字节数组 | 1.0 |
| getBytes(Charset) | 指定编码转换 | 1.6 | |
| 其他 | repeat() | 重复字符串 | 11 |
| indent() | 缩进处理 | 12 | |
| transform() | 转换函数 | 12 | |
| translateEscapes() | 转义字符转换 | 15 | |
| stripIndent() | 去除缩进 | 15 |
总结:
- Java 8及以前:掌握基础方法
- Java 11:重点学习 strip()、isBlank()、repeat()、lines()
- Java 12+:了解 indent()、transform()、describeConstable()
- Java 15+:掌握文本块、stripIndent()、translateEscapes()、formatted()
java
// 1、charAt()
String str = "Hello World";
System.out.println("charAt(0): " + str.charAt(0)); // 'H'
System.out.println("charAt(6): " + str.charAt(6)); // 'W'
// 2、length()
// 1. 基本用法
String str1 = "Hello";
String str2 = "你好";
String str3 = "😊🎉";
System.out.println("Hello.length(): " + str1.length()); // 5
System.out.println("你好.length(): " + str2.length()); // 2
System.out.println("😊🎉.length(): " + str3.length()); // 4(emoji占2个字符)
// 3、split()
String csv = "apple,banana,orange,grape";
String[] fruits = csv.split(",");
System.out.println("CSV分割结果:");
for (String fruit : fruits) {
System.out.println("- " + fruit);
}
// 4、toString()
List<String> list = Arrays.asList("A", "B", "C");
System.out.println("List toString(): " + list.toString());
// 5、startsWith()
String str4 = "Hello World";
System.out.println("startsWith(\"Hello\"): " + str4.startsWith("Hello")); // true
System.out.println("startsWith(\"World\"): " + str4.startsWith("World")); // false
// 6、endsWith()
// 1. 基本用法
String str5 = "Hello World";
System.out.println("endsWith(\"World\"): " + str5.endsWith("World")); // true
System.out.println("endsWith(\"Hello\"): " + str5.endsWith("Hello")); // false
// 7、substring()
System.out.println("substring(6): " + str.substring(6)); // "World"
System.out.println("substring(0, 5): " + str.substring(0, 5)); // "Hello"
// 8、isEmpty()- 检查是否为空字符串
String empty = "";
String spaces = " ";
String normal = "Hello";
System.out.println("\"\".isEmpty(): " + empty.isEmpty()); // true
System.out.println("\" \".isEmpty(): " + spaces.isEmpty()); // false(有空格字符)
System.out.println("\"Hello\".isEmpty(): " + normal.isEmpty()); // false
// 9、contains() - 检查是否包含子串
String text = "Hello World, Welcome to Java Programming";
System.out.println("contains(\"World\"): " + text.contains("World")); // true
System.out.println("contains(\"Java\"): " + text.contains("Java")); // true
System.out.println("contains(\"Python\"): " + text.contains("Python")); // false
// 10. lastIndexOf() - 返回指定字符/字符串最后一次出现的位置
String str10 = "Hello World, Hello Java";
int lastIndex = str10.lastIndexOf("Hello");
System.out.println("lastIndexOf(\"Hello\"): " + lastIndex); // 输出:13
// 11. toCharArray() - 将字符串转换为字符数组
String str11 = "Java";
char[] charArray = str11.toCharArray();
System.out.print("toCharArray(): ");
for(char c : charArray) {
System.out.print(c + " "); // 输出:J a v a
}
System.out.println();
// 12. indexOf() - 返回指定字符/字符串第一次出现的位置
String str12 = "Programming";
int firstIndex = str12.indexOf('g');
System.out.println("indexOf('g'): " + firstIndex); // 输出:3
// 13. toLowerCase() - 将字符串转换为小写
String str13 = "HELLO WORLD";
String lowerCase = str13.toLowerCase();
System.out.println("toLowerCase(): " + lowerCase); // 输出:hello world
// 14. toUpperCase() - 将字符串转换为大写(注意:应该是toUpperCase,不是toUpCase)
String upperCase = str13.toUpperCase();
System.out.println("toUpperCase(): " + upperCase); // 输出:HELLO WORLD
// 15. compareTo() - 按字典顺序比较两个字符串
String str6 = "apple";
String str7 = "banana";
int compareResult = str6.compareTo(str7);
System.out.println("compareTo(): " + compareResult); // 输出:负数(因为"apple" < "banana")
// 16. trim() - 去除字符串首尾的空白字符
String str8 = " Hello Java ";
String trimmed = str8.trim();
System.out.println("trim(): \"" + trimmed + "\""); // 输出:"Hello Java"
// 17. replace() - 替换字符串中的字符或字符序列
String str9 = "I like cats. Cats are cute.";
String replaced = str9.replace("cats", "dogs");
System.out.println("replace(): " + replaced); // 输出:I like dogs. Cats are cute.
// 18. replaceAll() - 使用正则表达式替换所有匹配的子串
String str18 = "Phone: 123-456-7890";
String replacedAll = str18.replaceAll("\\d", "*");
System.out.println("replaceAll(): " + replacedAll); // 输出:Phone: ***-***-****
// 额外:replace()和replaceAll()的区别演示
String str19 = "a.b.c";
System.out.println("replace(\".\", \"-\"): " + str19.replace(".", "-")); // 输出:a-b-c
System.out.println("replaceAll(\".\", \"-\"): " + str19.replaceAll(".", "-")); // 输出:-----(正则中的.匹配任意字符)
}