网站首页 > 精选教程 正文
String的不可变性
核心概念: Java 中的 String 对象是不可变的。这意味着一旦 String 对象被创建,它的值就无法再被修改。任何对 String 的修改操作,实际上都会创建一个新的 String 对象。
内部实现: Java String 的内部实现使用一个字符数组来存储字符序列。当修改 String 时,会创建一个新的字符数组,并将修改后的字符复制到新数组中,最后返回一个指向新数组的 String 对象。
优点:
- 安全性: 不可变性可以保证多线程环境下 String 的安全使用,多个线程可以同时访问同一个 String 对象而不会出现数据不一致问题。
- 缓存: 由于 String 是不可变的,JVM 可以对 String 对象进行缓存,提高效率。
- 哈希值: 不可变性使得 String 可以作为 HashMap 的键,因为它的哈希值始终保持不变。
缺点:
- 性能: 创建新的 String 对象会消耗内存和 CPU 资源。
- 内存占用: 频繁创建新的 String 对象会导致内存占用过大。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
// ... 其他构造函数和方法 ...
}
从源码可以看出:
- String 类是 final 的,不可被继承。
- String 对象使用一个 final 的字符数组 value 来存储字符序列。
- String 对象有一个 hash 字段用于缓存哈希值,提高查找效率。
String的常用操作
String 类提供了一系列方法来操作字符串,例如:
- 创建字符串:
- new String("hello"):使用构造函数创建新的字符串对象。
- "hello":使用字面量创建字符串对象,并将其存储在 String 池中。
- 访问字符: charAt(index)
- 查找字符: indexOf(char)、lastIndexOf(char)
- 截取字符串: substring(beginIndex, endIndex)
- 比较字符串: equals(String)、equalsIgnoreCase(String)
- 转换大小写: toLowerCase()、toUpperCase()
- 替换字符串: replace(char oldChar, char newChar)
- 拆分字符串: split(String regex)
- 连接字符串: concat(String str)
- 格式化字符串: String.format(String format, Object... args)
- 其他: trim()、isEmpty()、length() 等等。
常量池
- String 常量池 是 JVM 中一个特殊的内存区域,用于存储 String 字面量。
- 当使用字面量创建 String 对象时,JVM 会先在常量池中查找是否存在相同的字符串对象。
- 如果存在,则直接返回该对象;如果不存在,则创建一个新的 String 对象并将其加入常量池。
String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2); // true
==上述代码中,str1 和 str2 引用的是同一个 String 对象,
因为它们都是通过字面量创建的,JVM 会将它们存储在常量池中
注意:
- 使用 new String("hello") 创建的字符串对象不会被加入常量池。
- 常量池中的对象是不可变的。
intern()方法
- intern() 方法用于将 String 对象加入常量池。
- 如果常量池中已经存在相同的字符串对象,则返回该对象;否则,创建一个新的 String 对象并将其加入常量池,然后返回该对象。
String str1 = new String("hello");
String str2 = str1.intern();
String str3 = "hello";
System.out.println(str1 == str2); // false
System.out.println(str2 == str3); // true
上述代码中,str1 是通过构造函数创建的,所以不会被加入常量池。str2 使用 intern() 方法将 str1 加入常量池,并返回常量池中的对象。str3 是通过字面量创建的,所以直接从常量池中获取对象。最终,str2 和 str3 引用的是同一个 String 对象。
StringBuilder和StringBuffer
核心概念: StringBuilder 和 StringBuffer 是可变的字符串类。它们允许在不创建新对象的情况下修改字符串内容。
区别:
- 线程安全性: StringBuffer 是线程安全的,而 StringBuilder 不是线程安全的。
- 性能: StringBuilder 的性能比 StringBuffer 高,因为它没有进行线程同步。
使用场景:
- 需要频繁修改字符串时: 使用 StringBuilder 或 StringBuffer 可以提高性能。
- 需要线程安全时: 使用 StringBuffer。
StringBuilder sb = new StringBuilder("hello");
sb.append(" world");
System.out.println(sb.toString()); // hello world
StringBuffer sb = new StringBuffer("Hello ");
sb.append("World!");
System.out.println(sb.toString()); // 输出:Hello World!
字符串的性能优化
优化 String 性能的方法:
- 使用字面量: 使用字面量创建字符串可以利用 String 池,提高效率。
- 避免重复创建字符串: 在需要多次使用同一个字符串时,可以使用 String 变量或 StringBuilder/StringBuffer 来缓存字符串。
- 使用 intern() 方法: 可以手动将 String 对象加入 String 池,以便重复使用。
- 使用 String.format() 方法: String.format() 方法比 + 操作符更有效率,特别是对于格式化操作。
- 使用 StringBuilder/StringBuffer: 当需要频繁修改字符串时,使用 StringBuilder/StringBuffer 可以提高性能。
其他
- String 比较: 使用 equals() 方法比较字符串内容,而不要使用 == 操作符。
- 空字符串: 空字符串是长度为 0 的字符串,可以使用 isEmpty() 方法判断字符串是否为空。
- Unicode 字符串: Java 使用 Unicode 编码来表示字符串,支持多种语言的字符。
- 上一篇: Java性能调优--代码篇:String内存优化
- 下一篇: LeetCode-131-分割回文串
猜你喜欢
- 2024-11-18 Python学习(十)字符串的常用操作详解「Ⅱ」
- 2024-11-18 java基础—string,值得java初学者收藏的文章
- 2024-11-18 Java将 PDF 拆分为多个 PDF 文件
- 2024-11-18 「LeetCode」分割回文串 II Java题解
- 2024-11-18 【算法题】1593. 拆分字符串使唯一子字符串的数目最大
- 2024-11-18 《Java程序设计》课程代码题(一)
- 2024-11-18 JAVA后台开发的瑞士军google guava 集合,字符串实测
- 2024-11-18 Java字符串相关面试题
- 2024-11-18 LeetCode笔记|131:分割回文串
- 2024-11-18 Java基础学习之与字符串相关的正则表达式
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)