Java11在String类上引入了一系列新的API增强,这些改进显著提升了开发者在处理字符串时的便捷性和效率。
以下是Java11中增强String API的主要新特性:
- String.repeat():重复给定次数的字符串。返回连接的字符串。
- String.isBlank():检查字符串是否为空或只有空格。
- String.strip():删除前导和尾随空格。
- String.stripLeading():删除前导空格。
- String.stripTrailing():删除尾随空格。
- String.lines():返回多行字符串的行流。
String.repeat()
repeat
方法允许你重复一个字符串指定的次数。这在需要快速生成重复字符串的场景中非常有用。
示例:
String str = "abc".repeat(3);
System.out.println(str); // 结果为 "abcabcabc"
String.isBlank()
isBlank
方法检查一个字符串是否为空或者仅包含空白字符(如空格、制表符、换行符等)。这是一个非常实用的方法,可以帮助你判断用户输入是否有效。
示例:
System.out.println("".isBlank()); // 输出 true
System.out.println(" ".isBlank()); // 输出 true
System.out.println("\t".isBlank()); // 输出 true
System.out.println("\n".isBlank()); // 输出 true
System.out.println("hello".isBlank()); // 输出 false
String.strip(), String.stripLeading(), String.stripTrailing()
这三个方法用于删除字符串的前导、尾随或前导和尾随的空白字符。
strip()
:删除字符串的前导和尾随空白字符。stripLeading()
:仅删除字符串的前导空白字符。stripTrailing()
:仅删除字符串的尾随空白字符。
示例:
String str = " hello, world! ";
System.out.println(str.strip()); // 输出 "hello, world!"
System.out.println(str.stripLeading()); // 输出 "hello, world! "
System.out.println(str.stripTrailing()); // 输出 " hello, world!"
String.lines()
lines
方法将字符串按行分隔,并返回一个Stream<String>
,其中每个元素是字符串中的一行。这对于处理多行文本或文件内容非常有用。
示例:
String str = "line1\nline2\nline3";
str.lines().forEach(System.out::println); // 分别打印三行
String类的重要变化
Java中的String
类在不同版本之间经历了一些重要的变化。以下是一些关键的变化:
Java6及之前
String
类内部使用字符数组(char[]
)来存储字符串数据。每个字符占用两个字节(16位),因为Java使用UTF-16编码。
Java7
Java7引入了String
类的内部优化,增加了一个称为“字符串池”的概念。这种优化可以减少内存使用和提高性能。
Java 9
Java9之前中的String是使用char[]数组来存储字符的,每个字符通常占用两个字节(在UTF-16编码下)。然而,对于只包含 ASCII字符(或LATIN-1字符集)的字符串,这会导致大量的空间浪费,因为ASCII字符实际上只需要一个字节来存储。
Java9对String
类进行了重大改动,改用byte[]
数组来存储字符串数据,并通过一个coder
字段来标识使用的是Latin-1还是UTF-16编码。对于仅包含Latin-1字符的字符串,这种方式可以节省一半的内存。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {private final byte[] value;private final byte coder;// ...
}
可以通过下面的代码来观察String内部使用Latin-1或UTF-16编码时,内部数组的情况和coder
字段的标识:
package com.morris.java11;import java.lang.reflect.Field;public class StringCoderDemo {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {Field valueField = String.class.getDeclaredField("value");valueField.setAccessible(true);Field coderField = String.class.getDeclaredField("coder");coderField.setAccessible(true);String aa = "hello";System.out.println(((byte[])valueField.get(aa)).length); // 5System.out.println(coderField.get(aa)); // 0String bb = "中a";System.out.println(((byte[])valueField.get(bb)).length); // 4System.out.println(coderField.get(bb)); // }
}
运行时增加此--add-opens java.base/java.lang=ALL-UNNAMED
JVM参数,否则会抛出Unable to make field private final byte[] java.lang.String.value accessible
错误。
Java 11
Java 11增加了一些实用的方法,如strip()
, isBlank()
, lines()
, repeat()
等,提升了字符串处理的便利性。内部结构保持与Java 9一致。
这些变化主要是为了提高性能和减少内存使用,同时也增加了字符串操作的便利性。每个版本的改进都对开发者在处理字符串时带来了不同程度的影响。
Compressed Strings与Compact Strings
Compressed Strings与Compact Strings是Java在处理字符串时所采用的两种不同机制,它们在Java的不同版本中有所体现,具体区别如下:
Compressed Strings(压缩字符串):
- 引入版本:Java 6。
- 特性:Compressed Strings对于每个字符占用一个字节(one byte per character)的情况使用byte[],而对于每个字
占用两个字节(two bytes per character)的情况则继续使用char[]。 - 启用与废弃:之前可以通过-XX:+UseCompressedStrings选项来启用这一特性,但它在Java 7中被废弃,并在Java 8中被完全移除。
Compact Strings(缩小字符串):
- 引入版本:Java 9。
- 特性:Compact Strings是Java 9中引入的一种新机制,用于取代Java 6中的Compressed Strings。它的实现更为彻底,完全使用byte[]来替代char[]存储字符串数据。同时,为了标识字符串是使用LATIN1编码还是UTF-16编码,新引入了一个字段coder。
- 优势:由于字符串在Java中非常常见,使用byte[]而非char[]可以显著减少堆内存的使用,这对于那些大量使用字符串的Java应用来说是一个重要的优化。
总结来说,Compressed Strings和Compact Strings都是Java为了优化字符串处理而引入的机制。Compressed Strings在Java 6中引入,但在后续版本中被废弃;而Compact Strings则在Java 9中引入,作为Compressed Strings的替代方案,它使用byte[]替代char[]来存储字符串数据,并通过引入新的字段来标识编码方式,从而实现了更高效的内存使用。