1. 字符序列
多个字符按照一定的顺序组成的列表就叫作字符序列。
String
字符串,不可变类型,因为底层存储值的数组是 final 修饰的StringBuffer
字符串缓冲区,是线程安全的StringBuilder
字符串构造器,非线程安全的CharBuffer
字符缓冲区
1.1 String
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence, Constable,
ConstantDesc
- 字符串
java.lang.String
可以用来表示多个字符,用""
引起来。字符串是引用数据类
型,默认值是nul
l 。 - JDK13 新增文本块(预览),在 JDK15 正式在字符串支持文本块,用
"""
表示。 - 字符串不可变,字符串内容储存元素是
final
修饰的,所以不可变。 - 字符串常量池不存重复的值。
1.2 字符串声明
//字符串声明
String str = "云创动力"; // 字面量 比较常用
String str1 = new String("云创动力"); // 字符串对象
// 文本块 """ 字符内容 """
String text = """
序号 姓名
1 张三
"abc";
'\t'
5201314
\\
//
""";
System.out.println(text);
序号 姓名
1 张三
"abc";
' '
5201314
\
//
1.3 String 类
字符串具有不可变特性。
public final class String
是用 final
修饰的类,在 Java
中用 final
修饰的类不能被继承,也就是说 String
没有子类。
jdk 1.8及之前版本:
private final char value[]; // 用于存放内容,字符串底层其实就是一个字符数组
private int hash; // 用来存放hash值
jdk1.9及以后版本:
private final byte value[]; // 用于存放内容,1.9之后使用字节数组存储
private int hash; // 用来存放hash值
private byte coder; // 编码方式,0 -LATIN1, 1 - UTF-16
> jdk 1.8之前字符串用char储存,jdk 1.9之后字符串用byte储存,为什么要这么改呢?
主要是为了节约
String
占用的内存,占用内存少引发另外一个好处就是减少GC
次数。
众所周知,在大多数 Java
程序的堆里, String
占用的空间最大,并且绝大多数 String
只有 Latin-1
字符,这些 Latin-1
字符只需要1个字节
就够了。 JDK9
之前, JVM
因为 String
使用 char
数组存储,每个 char
占2个字节
,所以即使字符串只需要1字节/字符,它也要按照2字节/字符进行分配,浪费了一半的内存空间。
JDK9
是怎么解决这个问题的呢?一个字符串出来的时候判断,它是不是只有 Latin-1
字符,如果是,就按照1字节/字符
的规格进行分配内存,如果不是,就按照2字节/字符
的规格进行分配( UTF-16 编码
),提高了内存使用率。
为什么用 UTF-16 而不用 UTF-8 呢,这就要从这两个字符集的设计说起了.
UTF-8
实际上是对空间利用效率最高的编码集,它是不定长的,可以最大限度利用内存和
网络。但是这种编码集只能用于传输和存储,并不适合拿来做 String
的底层实现。因为 String
有随机访问的方法
,所谓随机访问,就是 charAt
、 subString
这种方法。如果字符串中的每个字符占用的内存是不定长的,那么进行随机访问的时候,就需要从头开始数每个字符的长度,才能找到你想要的字符。
使用 UTF-16
编码将它们表示并存储为每个字符2个字节。
1.4 String常用方法
构造方法
在声明字符串时,使用字符串对象的方式来声明时使用的方法。
方法名 | 描述 |
---|---|
String( ) | 初始化新创建的 String 对象,使其表示空字符序列 |
String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的 String |
String(byte[] bytes, Charset charset) | 构造一个新的 String 用指定的字节的数组解码 charset |
String(byte[] bytes, String charsetName) | 构造一个新的 String 用指定的字节的数组解码 charsetName |
String(char[] value) | 构造一个新的 String 由指定的字符的数组构成 |
String(String original) | 初始化新创建的 String 对象,使其表示与参数相同的字符序列;换句话说,新创建的字符串是参数字符串的副本 |
String(StringBuffer buffer) | 分配一个新的字符串,其中包含当前包含在字符串缓冲区参数中的字符序列 |
String(StringBuilder builder) | 分配一个新的字符串,其中包含当前包含在字符串构建器参数中的字符序列 |
实例方法
方法名 | 返回值类型 | 描述 |
---|---|---|
length() | int | 返回当前字符串的长度 |
isEmpty() / isBlank() | boolean | 检查字符串是否为空 |
charAt(int index) | char | 返回指定索引处的字符 |
codePointAt(int index) | int | 返回指定索引处的Unicode代码点 |
codePointCount(int beginIndex, int endIndex) | int | 返回指定范围内的Unicode代码点数量 |
indexOf(String str) | int | 返回第一次出现指定字符串的索引位置,从头开始搜索 |
lastIndexOf(String str) | int | 返回最后一次出现指定字符串的索引位置,从末尾开始搜索 |
substring(int beginIndex) | String | 返回一个新字符串,包含从指定索引开始到原字符串末尾的字符序列 |
substring(int beginIndex, int endIndex) | String | 返回一个新字符串,包含从指定的开始索引到结束索引之间的字符序列 |
contains(CharSequence sequence) | boolean | 判断当前字符串是否包含指定的字符序列 |
startsWith(String prefix) | boolean | 判断当前字符串是否以指定的前缀开头 |
endsWith(String suffix) | boolean | 判断当前字符串是否以指定的后缀结尾 |
replace(char oldChar, char newChar) | String | 返回一个新字符串,将所有出现的旧字符替换为新字符 |
toLowerCase() | String | 返回一个新字符串,将所有字符转换为小写字母 |
toUpperCase() | String | 返回一个新字符串,将所有字符转换为大写字母 |
trim() | String | 返回一个新字符串,去除当前字符串的前导和尾部空格 |
strip() | String | 返回一个新字符串,去除当前字符串的前导和尾部空格 |
split(String regex) | String[] | 根据指定的正则表达式将当前字符串拆分为子字符串数组 |
join(CharSequence delimiter, CharSequence… elements) | String | 使用指定的分隔符将多个元素连接为一个字符串 |
equals(Object obj) | boolean | 比较当前字符串与指定对象是否相等 |
compareTo(String anotherString) | int | 比较当前字符串与另一个字符串的字典顺序 |
matches(String regex) | boolean | 判断当前字符串是否与指定的正则表达式匹配 |
练习
public class Demo02 {
public static void main(String[] args) {
String str = "海上月是天上月,眼前人是心上人。";
// 返回指定索引处的字符
System.out.println(str.charAt(0)); // 海
// codePointAt 返回指定索引处的Unicode代码点值。
System.out.println(str.codePointAt(1)); // 19978
char c = 19978;
System.out.println(c); // 上
// 子串
String sub = str.substring(8);
System.out.println(sub); // 眼前人是心上人。
sub = str.substring(0, 8);
System.out.println(sub); // 海上月是天上月,
// 判断字符串是否为空
System.out.println(str.isEmpty()); // false
System.out.println(str1.isBlank()); // true
// 去除两边的空格
System.out.println(str.strip());
System.out.println(str.trim());
// 去除前面的空格
System.out.println(str.stripIndent());
// 去除后面的空格
System.out.println(str.stripTrailing());
// 去除缩进
System.out.println(str.stripIndent());
// 比较字符串大小
String a = "Abcd";
String b = "abc";
System.out.println(a.compareTo(b)); // -32
// 忽略大小写
System.out.println(a.compareToIgnoreCase(b)); // 1
}
}