杰瑞科技汇

Java字符串定义有哪些关键点?

String 是什么?

在 Java 中,String(字符串)是一个用来表示字符序列的对象,任何用双引号 括起来的文本都是一个 String 对象。

Java字符串定义有哪些关键点?-图1
(图片来源网络,侵删)
String greeting = "Hello, World!";
String name = "Alice";
String emptyString = ""; // 空字符串

String 的关键特性

理解 String 的特性是掌握它的关键,主要有以下五点:

不可变性

这是 String 最重要的特性,一个 String 对象在创建之后,其内容(即它所指向的字符序列)是不可改变的

  • 如何实现不可变性?

    • String 类被 final 修饰,意味着它不能被继承,从而没有人能通过创建子类来改变它的行为。
    • 其内部存储字符的数组 private final char value[]; 也被 final 修饰,并且没有提供 public 的修改方法(如 set())。
    • 所有修改字符串内容的方法(如 substring(), replace(), concat() 等)实际上都不会修改原有的字符串对象,而是创建并返回一个新的 String 对象来保存修改后的结果。
  • 示例:

    Java字符串定义有哪些关键点?-图2
    (图片来源网络,侵删)
    String s1 = "hello";
    String s2 = s1.toUpperCase(); // s1 没有改变,s2 指向一个新的 "HELLO" 对象
    System.out.println(s1); // 输出: hello
    System.out.println(s2); // 输出: HELLO
    s1 = s1 + " world"; // s1 指向了一个新的 "hello world" 对象,原来的 "hello" 对象等待被回收
    System.out.println(s1); // 输出: hello world
  • 不可变性的好处:

    • 线程安全不可变,所以多个线程可以同时访问一个 String 对象而无需进行同步,不会出现数据竞争问题。
    • 安全:在 Java 中,String 被广泛用于存储密码、文件路径等敏感信息,不可变性确保了这些信息在创建后不会被意外或恶意地修改。
    • 性能优化:字符串是不可变的,所以可以安全地被共享和缓存,Java 虚拟机为了优化字符串的性能,引入了一个特殊的内存区域——字符串常量池

字符串常量池

这是一个位于堆内存中的特殊缓存区,专门用来存储字符串字面量()。

  • 工作原理

    1. 当你使用 String s = "hello"; 这种方式创建字符串时,JVM 首先会检查字符串常量池中是否已经存在 "hello" 这个字符串。
    2. 如果存在,则直接返回池中该字符串的引用,不会创建新对象。
    3. 如果不存在,则会在池中创建一个新的 "hello" 对象,然后将其引用返回。
  • new 关键字的区别: 使用 new 关键字创建字符串(String s = new String("hello");)时,JVM 不会检查字符串常量池,而是直接在堆内存中创建一个新的对象,即使池中已经存在相同内容的字符串。

  • 示例:

    String s1 = "hello"; // 在常量池中创建 "hello"
    String s2 = "hello"; // 直接从常量池中引用 "hello",s1 和 s2 指向同一个对象
    System.out.println(s1 == s2); // 输出: true (比较的是内存地址)
    System.out.println(s1.equals(s2)); // 输出: true (比较的是内容)
    String s3 = new String("hello"); // 在堆中创建一个新的 "hello" 对象
    System.out.println(s1 == s3); // 输出: false (s1指向池,s3指向堆)
    System.out.println(s1.equals(s3)); // 输出: true (内容相同)

char[] 的关系

String 的内部实现是基于一个 char 数组的,这个数组是 private final 的,保证了字符串内容的封装性和不可变性。

// 这是 String 类内部的一个简化版结构
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
    // ... 其他代码
}

广泛使用

String 是 Java 中最常用的类之一,几乎所有程序都会用到它,它被用于:

  • 存储用户输入、文件内容、网络数据等。
  • 作为方法参数和返回值。
  • 在日志、调试和显示信息中扮演核心角色。

性能考量

由于字符串的不可变性,在循环中进行大量的字符串拼接操作(如 )可能会造成性能问题,因为每次拼接都会创建一个新的 String 对象,增加 GC(垃圾回收)的压力。

不推荐的做法:

String result = "";
for (int i = 0; i < 1000; i++) {
    result += "a"; // 每次循环都创建一个新的 String 对象
}

推荐的做法: 对于频繁的字符串修改操作,应使用 StringBuilderStringBuffer,它们内部使用可变的字符数组,修改成本极低。

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append("a"); // 在原有对象上进行修改,高效
}
String result = sb.toString();
  • StringBuilder:非线程安全,但性能更高,单线程环境下推荐使用。
  • StringBuffer:线程安全,方法大多被 synchronized 修饰,性能稍差,多线程环境下使用。

String 的常用方法

方法 描述 示例
length() 返回字符串的长度。 "abc".length() -> 3
charAt(int index) 返回指定索引处的字符。 "hello".charAt(1) -> 'e'
substring(int beginIndex) 返回从 beginIndex 开始到结尾的子字符串。 "HelloWorld".substring(5) -> "World"
substring(int begin, int end) 返回从 beginend-1 的子字符串。 "HelloWorld".substring(0, 5) -> "Hello"
indexOf(String str) 返回子字符串 str 第一次出现的索引,未找到则返回 -1 "Hello".indexOf("ll") -> 2
lastIndexOf(String str) 返回子字符串 str 最后一次出现的索引。 "HelloHello".lastIndexOf("l") -> 9
toUpperCase() / toLowerCase() 将字符串转换为大写/小写,并返回新字符串。 "aBc".toUpperCase() -> "ABC"
trim() 去除字符串两端的空白字符,并返回新字符串。 " hello ".trim() -> "hello"
replace(char old, char new) / replace(CharSequence old, CharSequence new) 替换所有匹配的字符或子序列,并返回新字符串。 "hello".replace('l', 'p') -> "heppo"
split(String regex) 根据给定的正则表达式分割字符串,返回一个字符串数组。 "a,b,c".split(",") -> ["a", "b", "c"]
equals(Object anObject) 是否相等。 "abc".equals("ABC") -> false
equalsIgnoreCase(String anotherString) 忽略大小写是否相等。 "abc".equalsIgnoreCase("ABC") -> true
比较内存地址是否相等(是否是同一个对象)。 s1 == s2 (如果都指向常量池中的"hello") -> true
compareTo(String anotherString) 按字典顺序比较两个字符串。 "abc".compareTo("abd") -> -1 (因为 'c' < 'd')
特性 描述 影响
不可变性 不可变。 线程安全、安全、利于字符串常量池优化。
字符串常量池 特殊的缓存区,存储字符串字面量。 节省内存,"abc" == "abc" 可能为 true
final 不能被继承。 保证 String 内部实现的稳定性和不可变性。
基于 char[] 内部实现是字符数组。 提供了高效的字符序列操作。

理解 String 的这些核心特性和常用方法,是进行 Java 开发的基础,记住它的不可变性字符串常量池机制,是写出高效、健壮代码的关键。

分享:
扫描分享到社交APP
上一篇
下一篇