字符与字符串
字符数据类型是Java中的基本数据类型之一,字符是用单引号引住的单个引号。字符串是用双引号引住的任意个字符,字符串其实就是字符组成的序列。
字符串的默认值是null
字符串的声明
String str = "你好"; // 字符串常量 String str1 = new String("你好世界"); // 字符串对象
// 文本块声明 // Text Block 文本块声明 // The six characters w i n t e r String season = """ winter"""; // The seven characters w i n t e r LF(换行) String period = """ winter abc """; // The ten characters H i , SP(空格) " B o b " LF(换行) String greeting = """ Hi, "Bob" """; // The eleven characters H i , LF(换行) SP(空格) " B o b " LF(换行) String salutation = """ Hi, "Bob" """; // The empty string (zero length) "" String empty = """ """; // The two characters " LF String quote = """ " """; // The two characters \ LF String backslash = """ \\ """;
public class Test { public static void main(String[] args) { // 文本块声明 String str = """ 高尔基说:"书籍是人类进步的阶梯"。 """; System.out.println(str); } }
String 类
字符串具有不可变特性
字符串类时final修饰的类,说明它是不可继承的或者说是没有子类的。
在String类中,是利用byte数组来存储数据的,并且用了final修饰,说明了字符串不可变。
在jdk8之前是利用char数组来存储字符串数据的,但是在之后是利用byte来存储的。
主要是为了节约 String 占用的内存,占用内存少引发另外一个好处就是减少 GC 次数。 众所周知,在大多数 Java 程序的堆里, String 占用的空间最大,并且绝大多数 String 只有 Latin-1 字符,这些 Latin-1 字符只需要1个字节就够了。 JDK9 之前, JVM 因为 Str ing 使用 char 数组存储,每个 char 占2个字节,所以即使字符串只需要1字节/字符,它 也要按照2字节/字符进行分配,浪费了一半的内存空间。
JDK9 是怎么解决这个问题的呢?
一个字符串出来的时候判断,它是不是只有 Latin-1 字 符,如果是,就按照1字节/字符的规格进行分配内存,如果不是,就按照2字节/字符的规 格进行分配( UTF-16 编码),提高了内存使用率。
为什么用 UTF-16 而不用 UTF-8 呢?
这就要从这两个字符集的设计说起了。 UTF-8 实际上是对空间利用效率最高的编码集,它是不定长的,可以最大限度利用内存和 网络。但是这种编码集只能用于传输和存储,并不适合拿来做 String 的底层实现。因为 S tring 有随机访问的方法,所谓随机访问,就是 charAt 、 subString 这种方法。如果字符 串中的每个字符占用的内存是不定长的,那么进行随机访问的时候,就需要从头开始数每 个字符的长度,才能找到你想要的字符。 使用 UTF-16 编码将它们表示并存储为每个字符2个字节。 对于 JDK9 和更高版本,默认情况下,如果 String 的行为已更改为对字符串使用紧凑表示 形式。