为什么 JDK9 把 String 中 char 数组改成了 byte 数组?

大家好,我是鸭鸭!

此答案节选自鸭鸭最近弄的面试刷题神器面试鸭 ,更多大厂常问面试题,可以点击进行阅读哈!

目前这个面试刷题神器刚出,有网页和小程序双端可以使用!


回归面试题!为什么 JDK9 把 String 中 char 数组改成了 byte 数组?

这个题目的答案其实非常简单:这个操作主要是为了节省内存空间,提高内存利用率

在 JDK 9 之前,String 类是基于 char[] 实现的,内部采用 UTF-16 编码,每个字符占用两个字节。

image.png

但是,如果当前的字符仅需一个字节的空间,这就造成了浪费。例如一些 Latin-1 字符用一个字节即可表示。

因此 JDK 9 做了优化采用 byte 数组来实现:

image.png

并引入了 coder 变量来标识编码方式(Latin-1 或 UTF-16)。对于大多数只包含 Latin-1 字符(即每个字符可以用一个字节表示)的字符串,内存使用量减半。

扩展 Latin1

Latin1 是国际标准编码 ISO-8859-1 的别名。Latin1 也是单字节编码,在 ASCII 编码的基础上,利用了 ASCII 未利用的最高位,扩充了 128 个字符,因此 Latin1 可以表示 256 个字符,并向下兼容 ASCII。

Latin1收录的字符除 ASCII 收录的字符外,还包括西欧语言、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。欧元符号出现的比较晚,没有被收录在 ISO-8859-1 当中,在后来的修订版 ISO-8859-15 加入了欧元符号。

Latin1的编码范围是 0x00-0xFF,ASCII的编码范围是 0x00-0x7F。

Latin1 相对 ASCII 而言,较少被提及,其实 Latin1 的使用还是比较广泛的,比如 MySQL(8.0之前)的数据表存储默认编码就是 Latin1。

最后

最后再推荐下鸭鸭目前努力在做面试小程序神器面试鸭 ,已经有 3000 多道面试题目啦,欢迎大家来阅读!如果大家有不会的面试题,也可以在面试鸭内反馈!鸭鸭会第一时间为大家解答!

我是鸭鸭,我们下期见~

<think>好的,我现在需要回答用户关于JavaString是否可以通过数组方式访问成员的问题。首先,我要回忆一下JavaString类的结构。记得String内部确实是用字符数组来存储数据的,也就是char[],不过在Java 9之后,为了优化存储空间,改用了byte数组加上编码标志位。不过用户的问题是关于访问方式,而不是内部实现。 接下来,用户问的是是否可以用数组的方式访问String的成员,也就是像str[0]这样获取第一个字符。这时候我要确认Java的语法是否允许这种操作。JavaString类并没有像数组那样通过下标直接访问的方法。比如,数组可以用arr[index],而String则需要使用方法,比如charAt(index)。因此,直接使用数组语法访问会导致编译错误。 不过,用户可能知道其他语言如Python或JavaScript允许这样的操作,所以需要明确指出Java的不同之处。另外,可能需要说明为什么Java不提供这样的语法,可能是出于封装性的考虑,或者保持String的不可变性。 然后,用户可能想知道替代方案,比如如何将String转换为字符数组,这样就可以用数组的方式访问了。这时候需要提到toCharArray()方法,这样用户就可以得到一个char数组,然后通过索引访问每个字符。 同时,还要提醒用户使用charAt()方法的好处,比如不需要创建额外的数组副本,节省内存,特别是处理大字符串时更高效。此外,还要注意索引越界的问题,无论是用charAt还是数组转换,都需要确保索引在有效范围内,否则会抛出异常。 最后,可能需要举例说明正确的用法和错误的尝试,让用户更清楚。例如,直接使用str[0]会导致编译错误,而使用str.charAt(0)或者转换为char数组后访问都是可行的。</think>在Java中,**String对象不能直接通过数组下标(方括号`[]`)访问字符**,但可以通过以下两种方式实现类似操作: --- ### **一、底层原理剖析** ```java // String内部存储结构(JDK9+优化后) public final class String implements Serializable, Comparable<String> { private final byte[] value; // 存储字节数据 private final byte coder; // 编码标识(LATIN1=0, UTF16=1) } ``` --- ### **二、正确访问方式** #### 1. **charAt() 方法** ```java String str = "Hello"; char firstChar = str.charAt(0); // 正确:返回&#39;H&#39; ``` #### 2. **转换为字符数组** ```java char[] charArray = str.toCharArray(); char firstChar = charArray[0]; // 正确:返回&#39;H&#39; ``` --- ### **三、错误尝试示例** ```java // 编译错误:String类型不支持数组访问操作符 char c = str[0]; // ❌ 错误写法 ``` --- ### **四、性能对比** | 访问方式 | 时间复杂度 | 空间复杂度 | 适用场景 | |--------------|----------|----------|---------------------| | charAt() | O(1) | O(1) | 单次随机访问 | | toCharArray()| O(n) | O(n) | 需要频繁修改字符 | --- ### **五、特殊场景注意** ```java // 处理代理对(Surrogate Pairs)的正确方式 String emoji = "😊"; int codePoint = emoji.codePointAt(0); // 返回128522(正确获取Unicode码点) ``` --- **最佳实践建议**: 1. **优先使用charAt()**:避免创建不必要的数组副本 2. **批量操作用数组转换**:需要修改字符时使用`char[]` 3. **注意Unicode扩展字符**:使用`codePointAt()`处理表情符号等特殊字符
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值