玖叶教程网

前端编程开发入门

java string 深入解析(java stringutils.isempty)

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 编码来表示字符串,支持多种语言的字符。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言