在过去的两天里,我一直在阅读关于编写Unicode Java 9 compact Strings的信息。但有一点我不明白。
关于字节数据类型
1)。 8位存储的范围是-128到127
问题
1)。为什么Java没有像char无符号16位那样实现它?我的意思是它将在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相同。
我尝试过像codepoint 128048这样的最难的例子,我在String.value变量中看到像这样的字节数组。
0 = 61
1 = -40
2 = 48
3 = -36
我知道这个代码点需要4个字节,但我知道如何将char []转换为byte [],但我不知道String如何处理这个byte []数据。
对不起,如果这个问题很简单,对不起任何打字英语都不是我的自然语言,非常感谢。
为什么Java没有像char无符号16位那样实现它?我的意思是它将在0.256的范围内,因为从0到127只能保持Ascii值,但是如果我将值设置为200,则会发生什么情况会延长ascii将溢出到-56。
Java的原始数据类型在四分之一世纪前用Java 1.0解决。紧凑的字符串是在不到两年前的Java 9中引入的。这个新功能仅仅是一个实现细节,并不能证明Java类型系统的基本更改是正确的。
除此之外,您正在查看存储在一个字节中的数据的一种解释。为了表示iso-latin-1单位,解释与Java的内置签名byte
相同的数据是否会导致正数或负数完全无关紧要。
同样,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);
-56
200
这两个数字,-56
和200
只是对位模式11001000
的不同解释,而包含位模式byte
的11001000
的iso-latin-1解释是字符È
。
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相同”时,你应该问自己,它是如何知道11001000
的位模式byte
首先是-56
?
System.out.println(value[0]);
与普通的计算机算术相比,byte
(或int
)转换为String
,实际上是昂贵的操作。这种转换操作经常被忽略,因为它被定义为打印byte
的默认方式,但并不比转换为String
将值解释为无符号数量更自然。为了进一步阅读,我推荐Two's complement。
这是因为并非字符串中的所有字节都被解释为相同。这取决于字符串的character encoding。
例:
这意味着,如果要将字符串表示为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
回到这个问题,开发人员这样做的动机是减少字符串的内存占用。并非所有字符串都使用char
提供的所有16位。
编辑:Code here