char[] 到 byte[] 背后的 Java 11 Compact Strings 魔术

在过去的两天里,我一直在阅读有关编码 Unicode Java 9 紧凑字符串的信息,我感觉很好。但是有些东西我不明白。


关于字节数据类型


1)。是一个 8 位存储范围从 -128 到 127


问题


1)。为什么Java没有像char unsigned 16 bits那样实现它?我的意思是它会在 0.256 的范围内,因为从 0 到 127 我只能保存一个 Ascii 值,但是如果我将值设置为 200 会发生什么,扩展的 ascii 会溢出到 -56。


2)。负值是否意味着我的意思是我尝试了一个使用 Java 11 的简单示例


final char value = (char)200;//in byte would overflow

final String stringValue = new String(new char[]{value});

System.out.println(stringValue);//THE SAME VALUE OF JAVA 8

我检查了 String.value 变量,我看到了一个字节数组


System.out.println(value[0]);//-56

出现与之前相同的问题,-56 是否意味着其他语言中的(负值)这个溢出被检测到返回值 200?Java 怎么知道 -56 值与 char 中的 200 相同。


我尝试了最难的例子,比如代码点 128048,我在 String.value 变量中看到了一个这样的字节数组。


0 = 61 

1 = -40

2 = 48

3 = -36

我知道这个代码点需要 4 个字节,但我知道如何将 char[] 转换为 byte[] ,但我不知道 String 如何处理这个 byte[] 数据。


对不起,如果这个问题很简单,对不起,任何打字英语都不是我的自然语言,非常感谢。


慕田峪4524236
浏览 155回答 2
2回答

临摹微笑

为什么Java没有像char unsigned 16 bits那样实现它?我的意思是它会在 0.256 的范围内,因为从 0 到 127 我只能保存一个 Ascii 值,但是如果我将值设置为 200 会发生什么,扩展的 ascii 会溢出到 -56。Java 的原始数据类型在 25 年前的 Java 1.0 中得到了解决。不到两年前,Java 9 中引入了紧凑字符串。这个新特性只是一个实现细节,并不能证明 Java 类型系统的根本变化是合理的。除此之外,您正在查看存储在一个字节中的数据的一种解释。为了表示 iso-latin-1 单位,将相同的数据解释为 Java 内置的 signedbyte是否会导致正数或负数完全无关紧要。同样,Java 的 I/O API 允许将文件读入byte[]数组并将数组写byte[]回文件,这两个操作已经足以无损地复制文件,而不管其文件格式在解释其内容时是否相关。所以从 Java 1.1 开始以下工作:byte[] bytes = "È".getBytes("iso-8859-1");System.out.println(bytes[0]);System.out.println(bytes[0] & 0xff);-56200这两个数字,-56和200只是位模式的不同解释,而包含位模式的11001000iso-latin-1 解释是字符。byte11001000È值char也只是对两个字节数量的解释,即作为 UTF-16 代码单元。同样,char[]数组是计算机内存中具有标准解释的字节序列。我们也可以用这种方式解释其他字节序列。StringBuilder sb = new StringBuilder().appendCodePoint(128048);byte[] array = new byte[4];StandardCharsets.UTF_16LE.newEncoder()    .encode(CharBuffer.wrap(sb), ByteBuffer.wrap(array), true);System.out.println(Arrays.toString(array));将打印您看到的值,[61, -40, 48, -36].在类中使用byte[]数组的优点String是,现在可以选择解释,当所有字符都可以用这种编码表示时使用 iso-latin-1,否则使用 utf-16。可能的数字解释与字符串无关。但是,当你问“Java 怎么知道 -56 值与 200 相同”时,你应该问自己,它是如何知道11001000abyte的位模式-56在首位的?System.out.println(value[0]);与普通计算机算术相比,a byte(或 an int)到 a的转换实际上是一个昂贵的操作String。这种转换操作经常被忽略,因为它已被定义为打印 a 的默认方式,但并不比将值解释为无符号数量byte的转换更自然。String为了进一步阅读,我推荐二进制补码。

jeck猫

这是因为并非字符串中的所有字节都被解释为相同的。这取决于字符串的字符编码。例子:如果字符串是 UTF-8 字符串,则其字符大小为 8 位。在 UTF-16 字符串中,其字符大小为 16 位。ETC...这意味着,如果要将字符串表示为 UTF-8,则字符将通过一次读取 1 个字节来生成;如果是 16 位,则字符将通过一次读取 2 个字节来生成。看这段代码:data使用 UTF-8 和 UTF-16 将单字节数组转换为字符串。byte[] data = new byte[] {97, 98, 99, 100};System.out.println(new String(data, StandardCharsets.UTF_8));System.out.println(new String(data, StandardCharsets.UTF_16));这段代码的输出是:abcd // 4 bytes = 4 chars, 1 byte per char慢捤  // 4 bytes = 2 chars, 2 byte per char回到这个问题,开发人员这样做的动机是减少字符串的内存占用。并非所有字符串都使用所有 16 位 achar报价。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java