Java中字符串连接概述
在Java中,字符串连接是一项常见的操作。本教程将介绍几种字符串连接的方法,重点讲解如何使用concat()
方法和"+"运算符。最后,我们将讨论根据需求选择合适的方法。
2. 字符串连接方法
通常,Java中有多种方式来连接两个或多个字符串。让我们通过一些示例来看看每种方法的描述。
2.1 使用"+"运算符
在Java中,最常见的字符串连接方法之一是使用"+"运算符。
"+"运算符提供了比其他方法更灵活的字符串连接功能。首先,它不会对null值抛出异常。其次,它会将null转换为其字符串表示形式。此外,我们还可以用它来连接超过两个字符串。
下面是一个代码示例:
@Test
void whenUsingPlusOperatorANull_thenAssertEquals() {
String stringOne = "Hello ";
String stringTwo = null;
assertEquals("Hello null", stringOne + stringTwo);
}
在内部,编译器会将"+"运算符转换为StringBuilder
(或StringBuffer
)类及其append()
方法。
由于"+"运算符会无声地将参数转换为String
(通过对象的toString()
方法),**这样可以避免NullPointerException
**。然而,我们需要确保最终的字符串结果中包含"null"时对我们来说是适用的。
2.2 使用concat()
方法
String
类中的concat()
方法会在当前字符串末尾添加指定的字符串,并返回新的组合字符串。由于String
类是不可变的,原始字符串不会被改变。
让我们测试一下这个行为:
@Test
void whenUsingConcat_thenAssertEquals() {
String stringOne = "Hello";
String stringTwo = " World";
assertEquals("Hello World", stringOne.concat(stringTwo));
}
在上例中,stringOne
变量是基础字符串。使用concat()
方法,stringTwo
会被附加到stringOne
的末尾。由于concat()
操作是不可变的,所以我们需要显式地赋值。下个例子说明了这一点:
@Test
void whenUsingConcatWithOutAssignment_thenAssertNotEquals() {
String stringOne = "Hello";
String stringTwo = " World";
stringOne.concat(stringTwo);
assertNotEquals("Hello World", stringOne); // we get only Hello
}
为了获取最终连接的字符串,我们需要将concat()
的结果赋给一个变量:
stringOne = stringOne.concat(stringTwo);
assertEquals("Hello World", stringOne);
concat()
方法的另一个优点是可以连接多个String
对象,而且还可以添加空格和特殊字符:
@Test
void whenUsingConcatToMultipleStringConcatenation_thenAssertEquals() {
String stringOne = "Hello";
String stringTwo = "World";
String stringThree = ", in Jav";
stringOne = stringOne.concat(" ").concat(stringTwo).concat(stringThree).concat("@");
assertEquals("Hello World, in Jav@", stringOne);
}
至于null值,当前字符串和要附加的字符串都不能为null。否则,concat()
方法会**抛出NullPointerException
**:
@Test
void whenUsingConcatAppendANull_thenAssertEquals() {
String stringOne = "Hello";
String stringTwo = null;
assertThrows(NullPointerException.class, () -> stringOne.concat(stringTwo));
}
2.3 StringBuilder
类
首先,我们有StringBuilder
类。它提供了append()
方法进行字符串连接操作。以下是如何使用的例子:
@Test
void whenUsingStringBuilder_thenAssertEquals() {
StringBuilder builderOne = new StringBuilder("Hello");
StringBuilder builderTwo = new StringBuilder(" World");
StringBuilder builder = builderOne.append(builderTwo);
assertEquals("Hello World", builder.toString());
}
另一方面,StringBuffer
类提供了类似的连接功能,但与非线程安全的StringBuilder
不同,StringBuffer
是线程安全的。然而,它的性能略逊于StringBuilder
。它也像StringBuilder
一样具有append()
方法。
2.4 String
的format()
方法
另一种进行字符串连接的方式是使用String
类的format()
方法。通过使用格式化占位符(如%s
),我们可以根据它们的字符串值或对象来连接多个字符串:
@Test
void whenUsingStringFormat_thenAssertEquals() {
String stringOne = "Hello";
String stringTwo = " World";
assertEquals("Hello World", String.format("%s%s", stringOne, stringTwo));
}
2.5 Java 8及更高版本的连接方法
从Java 8开始,String
类的join()
方法可用于字符串连接。在这种情况下,方法的第一个参数是用于分隔要连接的字符串的分隔符:
@Test
void whenUsingStringJoin_thenAssertEquals() {
String stringOne = "Hello";
String stringTwo = " World";
assertEquals("Hello World", String.join("", stringOne, stringTwo));
}
Java 8新增了StringJoiner
类,它使用分隔符、前缀和后缀来连接字符串。以下是其使用的示例代码:
@Test
void whenUsingStringJoiner_thenAssertEquals() {
StringJoiner joiner = new StringJoiner(", ");
joiner.add("Hello");
joiner.add("World");
assertEquals("Hello, World", joiner.toString());
}
随着Java 8中流API(Stream API)的引入,我们有了Collectors
类,其中的joining()
方法。这个方法的工作原理类似于String
类的join()
方法,适用于集合。以下示例展示了其工作方式:
@Test
void whenUsingCollectors_thenAssertEquals() {
List<String> words = Arrays.asList("Hello", "World");
String collect = words.stream().collect(Collectors.joining(", "));
assertEquals("Hello, World", collect);
}
3. 选择方法
最后,如果我们要在concat()
方法和"+"运算符之间做出选择,我们需要考虑一些方面。
首先,concat()
方法只接受字符串。而"+"运算符可以接受任何类型并将其转换为字符串。另一方面,concat()
方法在遇到null值时会抛出NullPointerException
,而"+"运算符则不会。
此外,它们之间存在性能差异。concat()
方法的性能优于"+"运算符。后者总是创建一个新的字符串,不论字符串长度如何。另外,我们需要考虑的是,当要附加的字符串长度大于0时,concat()
方法才会创建新字符串;否则,它将返回相同的对象。
4. 总结
在这篇文章中,我们快速概述了Java中的字符串连接。详细介绍了如何使用concat()
方法和"+"运算符进行字符串连接,并进行了两者之间的比较分析,以确定在不同上下文中的选择。
本文中所有使用的代码片段可在GitHub上找到。