2012-03-03 99 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转义。

相关问题