7

Java 语言规范声明字符串中的转义符是“普通”C 语言的转义符,例如\nand \t,但它们也指定了从\0to 的八进制转义符\377。具体来说,JLS 规定:

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 个字符指定八进制代码?

4

4 回答 4

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

于 2012-03-03T04:59:48.180 回答
2

如果我能理解规则(如果我错了,请纠正我):

\ 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),因为每个 Javachar都是 Unicode UTF-16。

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

char 数据类型(以及因此 Character 对象封装的值)基于原始 Unicode 规范,该规范将字符定义为固定宽度的 16 位实体。此后,Unicode 标准已更改为允许表示需要超过 16 位的字符。合法代码点的范围现在是 U+0000 到 U+10FFFF,称为 Unicode 标量值。(参考 Unicode 标准中 U+n 符号的定义。)

从 U+0000 到 U+FFFF 的字符集有时称为基本多语言平面 (BMP)。码位大于 U+FFFF 的字符称为补充字符。Java 2 平台在 char 数组以及 String 和 StringBuffer 类中使用 UTF-16 表示。在此表示中,补充字符表示为一对 char 值,第一个来自高代理范围 (\uD800-\uDBFF),第二个来自低代理范围 (\uDC00-\uDFFF)。

编辑:

任何超出 8 位范围(大于一个字节)的有效八进制值都是特定于语言的。一些编程语言可能会进行匹配Unicode的实现;有些可能不会(将其限制为一个字节)。Java 绝对不允许它,即使它支持 Unicode。

一些限制为一字节八进制文字的编程语言(取决于供应商) :

  1. Java(所有供应商): - 一个八进制整数常量,以 0 或 base-8 中的一位数开头(最多 0377);\0 到 \7、\00 到 \77、\000 到 \377(八进制字符串文字格式)
  2. C/C++ (Microsoft) - 一个以 0 开头的八进制整数常量(最多 0377);八进制字符串文字格式 \nnn
  3. Ruby - 一个以 0 开头的八进制整数常量(最多 0377);八进制字符串文字格式\nnn

一些支持大于一字节的八进制文字的编程语言(取决于供应商) :

  1. Perl - 一个以 0 开头的八进制整数常量;八进制字符串文字格式\nnn参见http://search.cpan.org/~jesse/perl-5.12.1/pod/perlrebackslash.pod#Octal_escapes

一些编程语言不支持八进制文字

  1. C# -Convert.ToInt32(integer, 8)用于 base-8我们如何使用 c# 将二进制数转换为八进制数?
于 2012-03-03T03:30:10.960 回答
0

我不知道为什么八进制转义仅限于 unicode 代码点 0 到 255。这可能是出于历史原因。这个问题基本上没有答案,因为在 Java 设计期间没有不增加八进制转义范围的技术理由。

但是应该注意的是,unicode 转义和八进制转义之间没有那么明显的区别。八进制转义仅作为字符串的一部分进行处理,而 unicode 转义可以出现在文件中的任何位置,例如作为类名的一部分。另请注意,以下示例甚至无法编译:

String a = "\u000A";

原因是 \u000A 在很早的阶段(基本上是在加载文件时)扩展为换行符。以下代码不会产生错误:

String a = "\012";

\012在编译器解析代码后展开。这也适用于其他转义符,如 \n、\r、\t 等。

所以总而言之:unicode转义不是八进制转义的替代品。它们是完全不同的概念。特别是,为了避免任何问题(如上面的 \u000A),应该对代码点 0 到 255 使用八进制转义,对 255 以上的代码点使用 unicode 转义。

于 2012-09-09T20:48:13.457 回答
0

\0-\377 八进制转义符也继承自 C,并且该限制在字符 == 字节(至少在 wchar_t 之前的宁静日子)这样的语言中具有相当大的意义。

于 2012-03-03T05:00:59.473 回答