2012-03-03 19 views
6

Java語言規範指出字符串內部的轉義符是「正常」C類轉義符,如\n\t,但它們還指定從\0\377的八進制轉義符。具體來說,JLS規定:爲什麼Java八進制轉義只能達到255?

OctalEscape: 
    \ OctalDigit 
    \ OctalDigit OctalDigit 
    \ ZeroToThree OctalDigit OctalDigit 

OctalDigit: one of 
    0 1 2 3 4 5 6 7 

ZeroToThree: one of 
    0 1 2 3 

這意味着像\4715是非法的,儘管它的Java字符的範圍內是(因爲Java的字符不是字節)。

爲什麼Java有這個任意限制?你打算如何爲超過255的字符指定八進制代碼?

+1

255是基本的ASCII限制,如果我沒有弄錯,那麼每個基本的ASCII字符都有一個。你不應該爲此感到高興嗎? \ 4715之所以不能上去,是因爲它超過了255,這是標準的ASCII限制= D(我不善於解釋,指的是回答者) – 2012-03-03 03:47:19

+1

@Shingetsu:ASCII限制是127,而不是255 。_Bytes_被限制爲255,除非你在談論Java字節,由於一些奇怪的原因,它們被簽名爲:-)但是Java字符不是字節。 – paxdiablo 2012-03-03 04:30:43

+0

[另見](http://stackoverflow.com/questions/3537706/howto-unescape-a-java-string-literal-in-java/4298836) – 2014-04-02 01:11:07

回答

9

,也許是純粹的歷史原因,Java完全支持八進制轉義序列。這些轉義序列起源於C(或者可能在C的前身B和BCPL中),在像PDP-7這樣的計算機統治地球的日子裏,很多程序設計是在彙編中或直接在機器代碼中完成的,而八進制是首選的數字編寫指令代碼的基礎,沒有Unicode,只有ASCII,所以三個八進制數字足以代表整個字符集。

到Unicode和Java出現的時候,八進制已經讓位給十六進制,因爲當十進制不可以做時,首選的數字基礎會變成十六進制。所以Java的\u轉義序列需要十六進制數字。爲了讓C程序員感到舒適,可能支持八進制轉義序列,並且很容易將C程序中的'n'字符串常量複製到Java程序中。

請查看以下鏈接歷史瑣事:

http://en.wikipedia.org/wiki/Octal#In_computers
http://en.wikipedia.org/wiki/PDP-11_architecture#Memory_management

+1

+1另外請注意,即使除了編寫指令代碼之外,當您正在處理(例如)具有36位字和9位字符的體系結構時,八進制比十六進制更容易--12個八進制數字正好顯示一臺機器字,每個字符有3位數字。如果用9個十六進制數字表示相同的36位字,則無法輕鬆分辨各個字符的值。 – 2012-03-03 05:24:22

+0

正如我在下面的答案所解釋的那樣,\ uXXXX和八進制轉義序列在不同的階段被解析。 \ uXXXX轉義序列不是C的八進制轉義序列的擴展版本。只要將\ u000A放入一個字符串中,程序就會停止編譯。 – Sven 2013-08-19 05:41:57

1

如果我能理解規則(請糾正我,如果我錯了):

\ OctalDigit 
Examples: 
    \0, \1, \2, \3, \4, \5, \6, \7 

\ OctalDigit OctalDigit 
Examples: 
    \00, \07, \17, \27, \37, \47, \57, \67, \77 

\ ZeroToThree OctalDigit OctalDigit 
Examples: 
    \000, \177, \277, \367,\377 

\t\n\\不要下OctalEscape規則回落;他們必須在單獨的轉義字符規則下。

十進制255等於八進制377(使用Windows計算器在科學模式確認)

因此,一個三位數的八進制值落入的\000(0)到\377(255)

範圍因此,\4715不是有效的八進制值,因爲它超過三位八進制數規則。如果要訪問帶有十進制值4715的代碼點字符,請使用Unicode轉義符號\u來表示UTF-16字符\u126B(4715以十進制形式),因爲每個Java char都採用Unicode UTF-16。

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Character.html

The char data type (and therefore the value that a Character object encapsulates) are based on the original Unicode specification, which defined characters as fixed-width 16-bit entities. The Unicode standard has since been changed to allow for characters whose representation requires more than 16 bits. The range of legal code points is now U+0000 to U+10FFFF, known as Unicode scalar value. (Refer to the definition of the U+n notation in the Unicode standard.)

The set of characters from U+0000 to U+FFFF is sometimes referred to as the Basic Multilingual Plane (BMP). Characters whose code points are greater than U+FFFF are called supplementary characters. The Java 2 platform uses the UTF-16 representation in char arrays and in the String and StringBuffer classes. In this representation, supplementary characters are represented as a pair of char values, the first from the high-surrogates range, (\uD800-\uDBFF), the second from the low-surrogates range (\uDC00-\uDFFF).

被修改:

凡是超過8位範圍(大於一個字節)的有效八進制值是語言特定的。有些編程語言可能會繼續匹配Unicode實現;有些可能不會(限制爲一個字節)。 Java絕對不允許它,即使它具有Unicode支持。

一些編程語言(供應商相關),該限制一字節八進制文字

  1. 的Java(所有的供應商): - 以0或單位中開始八進制整數常數基數爲8(高達0377); \ 0到\ 7,\ 00到\ 77,\ 000到\ 377(八進制字符串文本格式)
  2. C/C++(Microsoft) - 以0開頭的八進制整數常量(最多0377);八進制字符串文字格式\nnn
  3. Ruby - 以0開頭的八進制整數常量(最多0377);八進制字符串文字格式\nnn

一些編程語言(供應商相關),支持高於一字節較大八進制文字

  1. Perl的 - 即從0開始一個八進制整數常數;八進制字符串文字格式\nnnhttp://search.cpan.org/~jesse/perl-5.12.1/pod/perlrebackslash.pod#Octal_escapes

不支持八進制文字一些編程語言:

  1. C# - 使用Convert.ToInt32(integer, 8)爲基8 How can we convert binary number into its octal number using c#?
+0

是的,我知道的限制。我的問題不是限制是什麼,而是爲什麼這些限制是存在的,因爲Java字符不限於0-255的範圍。我會澄清這個問題。 – paxdiablo 2012-03-03 04:32:21

+0

當然,Java對'String'和'char'使用Unicode 16位寬。但是現在,您正在使用escape \符號,並用它來表示一個八進制值,它只允許在Java八進制轉義格式中爲'\ 377'或在十進制值中爲255。 Java八進制轉義格式'\ 4715'不是有效的八進制轉義格式,因爲根據JLS中的OctalEscape規則它超過三位數。 – ecle 2012-03-03 04:33:59

+0

如果您想要在Unicode UTF-16 String/char下訪問超過255個代碼點,請使用Unicode符號'\ u'。所以,對於代碼點4715(?)是'\ u4715'(正確的形式,我認爲它應該是'\ u126B'爲十進制4715) – ecle 2012-03-03 04:41:08

0

的\ 0〜\ 377八個進制轉義也由C繼承和限制使得在語感相當數量像C這裏的字符==字節(至少在wchar_t之前的寧靜天)。

1

對於「爲什麼」這個問題的真正答案需要我們向Java語言設計師諮詢。我們無法做到這一點,我懷疑他們甚至有能力回答。 (可以you還記得20年前的詳細技術討論嗎?)

然而,對於這種「限制」一個合理的解釋是:

  • 八進制逃逸從C/C++,其中它們也限制爲8位借用,
  • 八進制是老式,並且IT人員通常更喜歡並且更加適應十六進制,並且
  • Java支持通過直接將其嵌入到源代碼中或通過使用Unicode轉義符來表達Unicode的方式,或者通過使用Unicode轉義符...不限於字符串和字符文字。

而且說實話,我從來沒有聽說過任何人(除了你)認爲,八進制文字應該長於在Java中8位。


順便提及,當我在計算字符集開始趨於硬件專用,以及常常小於 8位。在我的本科課程和畢業後的第一份工作中,我使用了擁有60位字和6位字符集的CDC 6000系列機器 - 我想我們稱之爲「顯示代碼」。 Octal在這方面非常好用。但隨着行業逐漸採用8/16/32/64位體系結構,人們越來越多地使用十六進制而不是八進制。

0

我知道沒有理由爲什麼八進制轉義限制爲unicode代碼點0到255.這可能是由於歷史原因。這個問題基本上沒有答案,因爲沒有技術上的理由不在Java的設計中增加八進制轉義的範圍。

但應該注意的是,unicode轉義和八進制轉義之間沒有如此明顯的區別。八進制轉義僅作爲字符串的一部分處理,而unicode轉義可以發生在文件中的任何位置,例如作爲類名的一部分。還要注意,下面的例子中甚至不會編譯:

String a = "\u000A"; 

的原因是,\ u000A在非常早的階段擴展到一個換行符(基本加載文件時)。下面的代碼不會生成一個錯誤:

String a = "\012"; 

的\ 012擴展後的編譯器解析的代碼。這也適用於\ n,\ r,\ t等其他轉義。

因此,總結:unicode轉義不是八進制轉義的替代。他們是一個完全不同的概念。特別是,爲避免任何問題(如上面所述),對於代碼點0到255應使用八進制轉義,對於超過255的代碼點,應使用unicode轉義。

相關問題