如何使用字符串stringbuilder和stringbuffer
在任何编程语言中,变量使用最多的数据类型是布尔值、数字基元类型值和字符的"字符串"(或数组)。与 C 或 C++相比,Java 处理字符串是不同的,因为:
- 在 Java 中,每个字符都是一个 16 位 Unicode 值,而不是 1 字节;
- 在 Java 中,字符串值由 String 对象管理;
- 在 Java 中,语法允许我们使用 Strings 作为基元数据类型(我们可以使用 + 运算符初始化它们)
- 在 Java 中,字符串是不可变的对象,这意味着一旦创建,它们就无法更改其值。
如何定义和初始化字符串
由于字符串值由 String 对象管理,因此可以使用默认语法创建它:
String s = new String(); String sWithValue = new String("Hello String !");
正如之前所说的,由于字符串是使用最多的数据类型之一,Java 语法允许我们把它们当做基元数据类型来使用,可以使用=
运算符:
String s = "Hello String !"; s = "Hello Java !";
在2 个字符串引用之间 使用等号=
时,不要忘记 Java 字符串是对象。我们将复制引用值而不是对象值。
String string1 = "Hello String !"; String string2 = string1; if(string1 == string2) System.out.println("相等"); else System.out.println("不相等);
将打印"相等",因为引用具有相同的值/地址,并在内存中生成这种情况:
什么是字符串是不可变的
不可变对象是一旦创建它,它无法更改其值的对象。
字符串是不可变的,基于前面的示例,让我们看看当我们执行类似操作时会发生什么:
String string1 = "Hello String !";; System.out.println(string1); string1 = "Hello !"; System.out.println(string1);
如果运行此示例,则结果是:
Hello String ! Hello !
第一印象是 string1 变量将其值从"Hello String!" 更改为"Hello!"
但这是错的,因为 字符串是不可变的
string1 是字符串引用,而不是对象;
因此,实际上是,第二个语句生成一个新的 String 对象,并且 [string1] 引用获取新对象的地址,如此变成:
什么是字符串常量池
在 Java 中,String 对象非常特殊(因为它们是不可变的),因为它们的值以特殊方式处理。为了有效地使用内存,JVM 通过将字符串值(尤其是字符串文本字面量)放在称为"字符串常量池"的特殊内存区域来管理字符串值(尤其是字符串文本字面量)。使用文本字面量值来初始化字符串时,JVM 会检查池以查看 String的值是否已在内存中。如果是,JVM将不会创建新值,JVM将把String的地址放在引用中。
基于此规则,下面这个示例将打印 “相等”
流程数据如下所示:
String string3 = "Hello String !"; String string4 = "Hello String !"; if(string3 == string4) // 比较字符串引用,而不是值 System.out.println("“相等”"); else System.out.println("不相等");
字符串常量池
(1) 在字符串常量池中设置值"Hello String !
(2) String4 引用
指向池中的现有字符串
使用new创建字符串和使用 =运算符创建字符串比较
如我们所看到的,有两种方法可以创建 String 对象:
使用new
: String s1 = new String(“Hello !”);
使用 等号=运算符
: String s2 = “Hello !”;
两者的区别是:
当我们使用 new 时,String 对象的行为类似于一个普通对象,这意味着其值被放置在堆中,而不是放在称为 String 常量池的特殊区域中。
因为,String 类是一个特殊的类,你不能继承它并重写它的功能。字符串类String是被标记为final的。
如何处理字符串
String 类有很多用于处理该值的方法。使用最多的是:
方法 | 说明 |
---|---|
charAt() | 返回给定索引的字符;索引将值从 0 到 length()-1; |
concat() | 将字符串追加到另一个字符串的末尾; 和加号+作用一样。 |
equals() | 比较两个字符串值(通过字符值比较) |
length() | 返回字符数;它不是数组的长度属性。这是一种方法 |
replace() | 替换字符 |
substring() | 返回子字符串 |
toLowerCase() | 将所有字符转换为小写 |
toString() | 返回 String 对象的值 |
toUpperCase() | 将所有字符转换为大写 |
trim() | 删除字符串首尾的空白字符 |
由于 String 是不可变的,因此在使用其中一些函数时必须注意,因为它们的结果是一个新的 String 对象。 这些方法不会影响当前对象。
什么是字符串构建器(StringBuilder)和字符串缓冲区(StringBuffer)
这两个类几乎相同(它们具有相同的 API)。它们之间的区别在于 StringBuilder(从 Java 5 添加)不是线程安全的,而且速度更快。
定义这两个类是因为它们以更高效的方式(内存)处理字符串值。原因之一是它们的值不存储在字符串常量池中,它们的行为与普通对象一样 - 当对象不是引用被 GC 销毁并且不会保留在字符串常量池中时。
StringBuilder 和 StringBuffer 背后的理念是提供具有大型流的高效 I/O 操作方法。
StringBuilder 和 StringBuffer 实例仅使用新运算符创建,而不是使用字符串:
如果要修改 StringBuilder 或 StringBuffer 的值,可以使用这些类中的方法。大多数使用的方法有:
方法 | 说明 |
---|---|
append() | 将参数添加到当前对象的末尾 |
delete() | 删除开始索引和结束索引之间的字符 |
insert() | 在给定的offset位置插入值 |
reverse() | 反转当前对象的值 |
toString() | 返回StringBuilder 或者 StringBuffer 对象的值object |
[这些方法影响调用对象的值] 比如:
StringBuilder sb1 = new StringBuilder("12345"); sb1.append("6789"); System.out.println(sb1); //打印 123456789 sb1.delete(0,2); System.out.println(sb1); //打印 3456789 sb1.reverse(); System.out.println(sb1); //打印 9876543
关于 StringBuilder 或 StringBuffer 的另一个事实是,我们可以调用多个方法 - 在同一对象上的链式方法。请记住,链式方法会影响调用对象,并且它们从左到右执行。
链式操作:
StringBuilder sb2 = new StringBuilder("Test"); sb2.append(" Java ").delete(0, 4).insert(0,"Begin"); System.out.println(sb2); //打印 Begin Java
输出结果: Begin Java