String字符串

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(".", "-")); // 输出:-----(正则中的.匹配任意字符)
    }
相关推荐
leo__5202 小时前
基于两步成像算法的聚束模式SAR MATLAB实现
开发语言·算法·matlab
Macbethad3 小时前
自动化测试技术报告
开发语言·lua
不会画画的画师3 小时前
Go开发指南:io/ioutil包应用和迁移指南
开发语言·后端·golang
2503_928411563 小时前
12.22 wxml语法
开发语言·前端·javascript
AM越.3 小时前
Java设计模式详解--装饰器设计模式(含uml图)
java·设计模式·uml
5980354154 小时前
【java工具类】小数、整数转中文大写
android·java·开发语言
JIngJaneIL4 小时前
基于java + vue个人博客系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
吃喝不愁霸王餐APP开发者4 小时前
Java后端服务在对接全国性霸王餐API时的多数据中心部署与就近调用策略
java·开发语言
从心归零4 小时前
springboot-jpa的批量更新方法
java·spring boot·spring