![](/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.