![](/img/trans.png)
[英]What is the difference between Java Non Heap Memory and Stack Memory? Are they Same if not what is the difference between them?
[英]Java - what are characters, code points and surrogates? What difference is there between them?
要在计算机中表示文本,您必须解决两件事:首先,您必须将符号映射到数字,然后,您必须用字节表示这些数字的序列。
代码点是标识符号的数字。 为符号分配数字的两个众所周知的标准是 ASCII 和 Unicode。 ASCII 定义了 128 个符号。 Unicode 目前定义了 109384 个符号,比 2 16多得多。
此外,ASCII 指定数字序列每个数字表示一个字节,而 Unicode 指定了几种可能性,例如 UTF-8、UTF-16 和 UTF-32。
当您尝试使用每个字符使用的位数少于表示所有可能值所需的位数时(例如使用 16 位的 UTF-16),您需要一些解决方法。
因此, 代理项是 16 位值,表示不适合单个两字节值的符号。
Java 在内部使用UTF-16来表示文本。
特别是, char
(字符)是包含 UTF-16 值的无符号两字节值。
您可以在 Javadoc 中找到java.lang.Character类的简短说明:
Unicode 字符表示
char
数据类型(以及Character
对象封装的值)基于原始 Unicode 规范,该规范将字符定义为固定宽度的 16 位实体。 Unicode 标准已经更改为允许表示需要超过 16 位的字符。 合法代码点的范围现在是U+0000
到U+10FFFF
,称为Unicode 标量值。 [..]从
U+0000
到U+FFFF
的字符集有时称为基本多语言平面 (BMP) 。 码位大于U+FFFF
的字符称为补充字符。 Java 平台在char
数组以及String
和StringBuffer
类中使用 UTF-16 表示。 在这种表示中,增补字符表示为一对char
值,第一个来自高代理范围 (\?-\?),第二个来自低代理范围 (\?-\?)。
换句话说:
代码点通常表示单个字符。 最初, char
类型的值与 Unicode 代码点完全匹配。 这种编码也被称为UCS-2 。
因此, char
被定义为 16 位类型。 但是,目前 Unicode 中有超过 2^16 个字符。 为了支持整个字符集,编码从固定长度编码UCS-2更改为可变长度编码UTF-16 。 在这种编码中,每个代码点由单个char
或两个char
。 在后一种情况下,这两个字符称为代理对。
UTF-16 的定义方式是,如果所有代码点都低于 2^14,则使用 UTF-16 和 UCS-2 编码的文本之间没有区别。 这意味着, char
可用于表示某些但不是所有字符。 如果一个字符不能在单个char
表示,则术语char
具有误导性,因为它仅用作 16 位字。
代码点通常是指 Unicode 代码点。 Unicode 词汇表是这样说的:
Codepoint(1) : Unicode 代码空间中的任何值; 即 0 到 10FFFF16 的整数范围。
在 Java 中,字符 ( char
) 是一个无符号的 16 位值; 即 0 到 FFFF。
如您所见,有更多 Unicode 代码点可以表示为 Java 字符。 然而,Java 需要能够使用所有有效的 Unicode 代码点来表示文本。
Java 处理这种情况的方法是将大于 FFFF 的代码点表示为一对字符(代码单元); 即代理对。 这些编码一个Unicode编码点比FFFF较大为一对16位值。 这使用了 Unicode 代码空间的子范围(即 D800 到 U+DFFF)保留用于表示代理对的事实。 技术细节在这里。
Java 使用的编码的正确术语是UTF-16 Encoding Form 。
您可能会看到的另一个术语是代码单元,它是特定编码中使用的最小表示单元。 在 UTF-16 中,代码单元是 16 位,对应于 Java char
。 其他编码(例如 UTF-8、ISO 8859-1 等)具有 8 位代码单元,而 UTF-32 具有 32 位代码单元。
字符这个词有很多含义。 这意味着在不同的上下文中的各种事物。 Unicode 词汇表给出了Character 的4 种含义,如下所示:
特点。 (1) 书面语言中具有语义价值的最小成分; 指的是抽象的含义和/或形状,而不是特定的形状(另见字形),尽管在代码表中,某种形式的视觉表示对于读者的理解是必不可少的。
特点。 (2) 抽象字符的同义词。 ( 抽象字符。用于组织、控制或表示文本数据的信息单元。)
特点。 (3) Unicode 字符编码的基本编码单位。
特点。 (4) 源自中国的表意文字的英文名称。 [见表意文字 (2)。]
然后是字符的Java特定含义; 即一个 16 位有符号数( char
类型),它可能代表也可能不代表 UTF-16 编码中的完整或部分 Unicode 代码点。
首先,unicode 是一个标准,它试图定义和映射所有语言的所有单个字符,从英文字母到中文、数字、符号等。
基本上 unicode 有很长的编号字符列表,其中代码点是指编号。
简而言之
UTF-16
编码方案表示的字符包含如此多的字符,所有字符都无法放入单个 Java 字符的分配空间中。简单的说:
Code unit
是char
占 2 个字节,编码为UTF-16
,每个字符不一定代表real world character
。Code point
始终是real world character
,它可能包含 1 或 2 个Code unit
,将其视为int
,可能需要 4 个字节。 让代码(测试用例)说出真相:
(需要 Java 9 +,由于 String 的方法codePoints()
和chars()
)
@Test
public void test() {
String s = "Hi, 你好, おはよう, α-Ω\uD834\uDD1E"; // last real character is "𝄞", that takes 2 code unit,
assertEquals(s.length(), s.toCharArray().length); // length() is based on char (aka code unit), not code point,
System.out.printf("input string:\t\"%s\"%n%n", s);
System.out.println("------ as code point (aka. real character) ------");
// code point,
s.codePoints().forEach(cp -> System.out.println(Character.toChars(cp)));
assertEquals(s.codePoints().count(), s.length() - 1); // last read character takes 2 unit code,
assertEquals(s.codePoints().count(), s.codePointCount(0, s.length())); // there is a method codePointCount() on String to get code point count on given char range,
System.out.println("\n------ as char (aka. code unit) ------");
// chars (aka. code unit),
s.chars().forEach(c -> System.out.println(Character.toChars(c)));
assertEquals(s.chars().count(), s.length()); // string length is the count of code unit, not code point,
}
输出:
input string: "Hi, 你好, おはよう, α-Ω𝄞" ------ as code point (aka. real character) ------ H i , 你 好 , お は よ う , α - Ω 𝄞 ------ as char (aka. code unit) ------ H i , 你 好 , お は よ う , α - Ω ? ?
最后一个真正的字符是𝄞
,它需要 2 个代码单元\?\?
,它是一个单一的code point
,当尝试分别打印 2 个代码单元时,它们无法识别,并显示?
对于每个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.