Java字符序列——String字符串1.1

前言回顾

java 中的8种基本数据类型。其中, char 是字符类型,占2个字节16位,默认值是 ‘\u0000’ 。用 char 类型的变量来表示单个字符,用单引号引起来。

多个字符按照一定的顺序组成的列表就叫作字符序列

String

——实现了 CharSequence 接口

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence, Constable,
ConstantDesc{	}

字符串是Java中表示字符序列的类。
字符串是不可变的,一旦创建就不能被修改。

字符串的表示

字符串java.lang.String可以用来表示多个字符,用""引起来。字符串是引用数据类
型,默认值是 null

//字符串声明
String str = "我是一个字符串"; // 字面量 比较常用
String str1 = new String("我是一个字符串对象"); // 字符串对象

JDK13 新增文本块(预览),在 JDK15 正式在字符串支持文本块,用 """ 表示。

// Text Block 文本块声明
// 注意第一个"""后面不能写文本,需从下一行开始写
String season = """
	winter""";

String类

public final class String 是用 final 修饰的类,在 Java 中用 final 修饰的类不能被继承,也就是说 String 没有子类。
** 回顾:**

在 Java 中,关键字 final 表示最终的。可以用来修饰类、方法、变量。

  1. 被 final 修饰的类,不能被继承
  2. 被 final 修饰的方法,不能被重写
  3. 被 final 修饰的变量,不能变。如果是基本数据类型不能重新赋值,如果是引用数据类型不
    能改变引用。

字符串具有不可变特性

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 8 及以前还是 jdk 9 及以后版本, value 属性都是 final 的。
就说明,字符串一旦声明就不可变。所以字符串拥有不可变性。

为什么要这么改呢?

主要是为了节约 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个字节

UTF-16 采用固定长度的编码单元(16位),这使得在访问字符串的任何部分时可以在 O(1) 时间内完成。而 UTF-8 使用可变长度编码单元,因此访问字符串中的字符可能需要 O(n) 时间,其中 n 是字符的位置。

对于 JDK9 和更高版本,默认情况下,如果 String 的行为已更改为对字符串使用紧凑表示形式。 java 命令文档现在这样说

-XX-CompactStrings

禁用紧凑字符串功能。 默认情况下,启用此选项。 启用此选项后,内部仅包含单字节字符的 Java 字符串将使用 ISO-8859-1 / Latin-1 编码在内部表示并存储为每个字符的单字节字符串。 这将只包含单字节字符的字符串减少了50%的空间。 对于包含至少一个多字节字符的 Java 字符串:使用 UTF-16 编码将它们表示并存储为每个字符2个字节。 禁用紧凑字符串功能会强制使用 UTF-16 编码作为所有 Java 字符串的内部表示。

需要注意的是,在 Java 9 之后,Java 引入了一些新的 API,如 String::codePoints 和String::getBytes 等,它们允许开发人员以不同的字符编码方式(包括 UTF-8)来处理字符串。这些 API 提供了更多的灵活性,以满足不同的需求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-今非昔比°

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值