1.什么是String
String是Java中的一个非常重要的类,它位于 java.lang 包下,因此在使用时不需要显式地导入。String类代表不可变的字符序列。
2.String的特点
1. 不可变性(Immutability)String对象是不可变的,这意味着一旦创建了String对象,就不能更改其值。每次对String的修改(如拼接、替换等)都会创建新的String对象。
2. 字符串常量池(String Constant Pool)为了优化性能和节省内存,Java虚拟机(JVM)维护了一个字符串常量池。当使用字符串字面量(即双引号括起来的字符串)创建String对象时,JVM会首先检查字符串常量池中是否已经存在相同内容的字符串。如果存在,则直接返回该字符串的引用;如果不存在,则在池中创建一个新的字符串并返回其引用。这避免了在内存中创建大量重复的字符串对象。
3. final类String类被声明为final,这意味着它不能被继承。这有助于保持String类的不可变性,因为子类可能会破坏这种不变性。
4. 丰富的APIString类提供了大量的方法来操作字符串,如查找、替换、比较、分割、连接等。这些方法使得字符串处理变得简单而高效。
5. 字符串拼接字符串拼接是常见的操作,但直接使用 + 运算符进行拼接在性能上可能不是最优的,特别是在循环或大量拼接的情况下。这是因为每次拼接都会创建新的String对象。为了提高性能,可以使用 StringBuilder 或 StringBuffer 类(后者是线程安全的)来进行字符串的拼接。
6. 字符串比较使用 == 运算符比较字符串时,实际上是比较两个字符串对象的引用是否相同。要比较字符串的内容是否相同,应该使用 equals() 方法。此外, equalsIgnoreCase() 方法用于忽略大小写比较字符串内容。
7. 字符串格式化可以使用 String.format() 方法进行字符串的格式化,类似于C语言中的 printf 函数。这允许开发者创建包含变量和表达式的格式化字符串。
3.字符串池
3.1定义
字符串池是一种特殊的存储机制,用于存储字符串字面量。当程序中创建一个字符串字面量时,如果该字符串已经存在于字符串池中,则会复用已有的字符串对象;否则,会在字符串池中创建一个新的字符串对象。
3.2字符串池的位置在Java 7及之前的版本中,字符串池位于永久代(Permanent Generation)中。永久代主要用于存储类和方法的信息,包括静态字段和常量池。字符串池就是作为常量池的一部分存在的从Java 8开始,永久代被元空间(Metaspace)所替代,字符串池也不再存储于永久代中。在Java 8中,字符串池默认位于堆内存中
3.3字符串池的作用减少内存消耗:由于字符串的不可变性(Immutable),相同的字符串字面量在内存中可以有多个副本。字符串常量池允许在内存中只存储一份相同的字符串字面量,而所有引用该字符串字面量的变量都指向这份单一的内存地址。这样可以有效地节省内存空间。共享机制:字符串常量池中的字符串是共享的,不同的对象或方法都可以引用同一个字符串对象,而不需要各自创建自己的副本。引用比较:当比较两个字符串是否相等时,如果这两个字符串都是字符串常量池中的字面量,那么比较它们的引用(即内存地址)会比比较它们的内容更加高效。因为引用比较是O(1)的时间复杂度,而内容比较(如使用equals()方法)可能需要遍历整个字符串,其时间复杂度与字符串的长度成正比。
3.4字符串池的注意事项内存泄漏:由于字符串常量池中的字符串对象不会被垃圾回收器回收,所以如果大量创建字符串对象并且不再使用时,可能会导致内存泄漏问题。因此,需要尽量避免大量创建无用的字符串对象。比较字符串:在比较字符串时,建议使用equals()方法而不是==操作符,以确保比较的是字符串的内容而不是引用地址。尽管在字符串常量池中,通过引用比较可以高效地判断字符串是否相等,但在处理非字符串常量池中的字符串时,使用equals()方法更为稳妥。
3.5字符串池的行为当你使用字符串字面量创建一个 String 对象时,如 "Hello" ,JVM 会首先检查字符串池中是否存在相同的字符串。如果不存在,则会将该字符串添加到字符串池中。如果已经存在,则会直接返回字符串池中的引用。当你使用 new String("Hello") 创建一个 String 对象时,一个新的 String 对象会在堆上创建,但字符串 "Hello" 也会被检查是否已经存在于字符串池中。如果不存在,会将其添加到字符串池中。
4.String中常用的方法
- length() : 返回字符串中的字符数。
- charAt(int index) : 返回指定索引处的字符。
- isEmpty() : 如果字符串为空字符串(长度为0),返回 true 。
- equals(Object anObject) : 如果两个字符串具有相同的字符序列,则返回
- trueequalsIgnoreCase(String anotherString) : 忽略大小写进行比较。
- concat(String str) : 将指定字符串连接到当前字符串的末尾。
- contains(CharSequence s) : 如果此字符串包含指定的字符序列,则返回 true 。
- startsWith(String prefix) : 如果此字符串以指定的前缀开头,则返回 true 。
- startsWith(String prefix, int toffset) : 如果此字符串从指定索引开始以指定的前缀开头,则返回
- trueendsWith(String suffix) : 如果此字符串以指定的后缀结尾,则返回 true 。
- indexOf(方法重载,参数类型不一致) : 返回指定字符在此字符串中首次出现的索引。
- lastIndexOf(方法重载,参数类型不一致) : 返回指定字符在此字符串中最后一次出现的索引。
- substring(int beginIndex) : 返回从指定索引开始的子字符串。
- substring(int beginIndex, int endIndex) : 返回从指定索引开始到指定索引结束的子字符串。
- replace(char oldChar, char newChar) : 替换字符串中所有出现的旧字符为新字符。
- replaceAll(String regex, String replacement) : 替换所有匹配给定正则表达式的子序列。
- split(String regex) : 根据给定的正则表达式拆分此字符串。
- matches(String regex) : 判断此字符串是否匹配给定的正则表达式。
- format(Locale l, String format, Object... args) : 根据指定的格式字符串和参数列表返回格式化的字符串。
- toUpperCase() : 将此字符串转换为大写。
- toLowerCase() : 将此字符串转换为小写。
- trim() : 删除字符串两端的空白字符。
- toString() : 返回此字符串的字符串表示形式(通常不需要显式调用,因为字符串已经是字符串形式)。
5.StringBuilder 和 StringBuffer区别
1. 线程安全性StringBuffer : 是线程安全的。它的方法都是同步的,可以在多线程环境中安全地使用,而不需要额外的同步措施。StringBuilder : 不是线程安全的。它的方法是非同步的,所以在多线程环境中使用时需要手动同步。
2. 性能StringBuffer : 由于方法是同步的,所以在多线程环境下,使用 StringBuffer 更安全但也可能稍微慢一些。StringBuilder : 由于方法是非同步的,所以在单线程环境下,使用 StringBuilder 通常比StringBuffer 快。
4. 使用场景StringBuffer : 推荐在多线程环境中使用。StringBuilder : 推荐在单线程环境中使用,或者当线程安全性不是主要考虑因素时使用。
5.2常用的方法
- append(...) : 向字符串追加内容。
- insert(...) : 在指定位置插入内容。
- delete(...) : 删除指定范围内的内容。
- reverse() : 反转字符串。
- setLength(int newLength) : 设置字符串的长度。
- toString() : 返回当前构建的字符串。
StringBuilder和StringBuffer的主要区别在于线程安全性和性能。在多线程环境下,如果需要频繁修改字符串内容,应使用StringBuffer;在单线程环境下,为了获得更好的性能,应使用StringBuilder。此外,两者在方法兼容性上保持一致,但StringBuffer在方法调用时可能会因为同步处理而稍慢一些。
标签:弯路,返回,String,StringBuffer,高级,池中,创建,字符串 From: https://blog.csdn.net/2301_76592091/article/details/144057146