Почему восьмеричные экранирования Java достигают 255? - PullRequest
6 голосов
/ 03 марта 2012

Спецификация языка Java гласит, что экранированные символы внутри строк - это "нормальные" C, такие как \n и \t, но они также указывают восьмеричные экранированные значения от \0 до \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?

Ответы [ 5 ]

9 голосов
/ 03 марта 2012

Вероятно, по чисто историческим причинам Java вообще поддерживает восьмеричные escape-последовательности.Эти escape-последовательности возникли в C (или, может быть, в предшественниках C B и BCPL), во времена, когда компьютеры, подобные PDP-7, управляли Землей, и большая часть программ была сделана на сборке или непосредственно в машинном коде, и восьмеричное было предпочтительным числомоснова для написания кодов инструкций, и не было Unicode, только ASCII, поэтому трех восьмеричных цифр было достаточно для представления всего набора символов.

К тому времени, когда появились Unicode и Java, восьмеричное в значительной степени уступило местошестнадцатеричное в качестве предпочтительной числовой базы, когда десятичное просто не будет.Так что у Java есть escape-последовательность \u, которая принимает шестнадцатеричные цифры.Восьмеричная escape-последовательность, вероятно, поддерживалась просто для того, чтобы программистам на C было удобно, и чтобы было легко копировать и вставлять строковые константы из программ на C в программы Java.

Проверьте эти ссылки на исторические мелочи:

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

1 голос
/ 03 марта 2012

Реальный ответ на вопрос «почему» потребовал бы от нас спросить разработчиков языка Java.Мы не в состоянии сделать это, и я сомневаюсь, что они даже смогут ответить.(Можете ли вы вспомнить подробные технические обсуждения, которые у вас были ~ 20 лет назад?)

Однако, правдоподобное объяснение этого "ограничения" заключается в следующем:

  • восьмеричноеEscape были заимствованы из C / C ++, в котором они также ограничены 8 битами,
  • восьмеричный старомодный формат, и ИТ-специалисты обычно предпочитают шестнадцатеричный формат и более удобны, а
  • поддерживает Javaспособы выражения Unicode, встраивая его непосредственно в исходный код или используя \u Unicode escape-коды ... которые не ограничиваются строковыми и символьными литералами.

И, честно говоря, яникогда не слышал, чтобы кто-то (кроме вас) утверждал, что восьмеричные литералы должны быть длиннее, чем 8 бит в Java.


Кстати, когда я начинал работать с наборами символовкак правило, зависит от аппаратного обеспечения и часто меньше 8 бит.В моей студенческой курсовой работе и моей первой работе после выпуска я использовал машины серии CDC 6000, которые имели 60-битные слова и 6-битный набор символов - «Код дисплея», я думаю, мы его назвали.В этом контексте Octal работает очень хорошо.Но по мере того, как индустрия двигалась к (почти) всеобщему принятию 16/32/32/64 битных архитектур, люди все чаще использовали шестнадцатеричное вместо восьмеричного.

1 голос
/ 03 марта 2012

Если я могу понять правила (поправьте меня, если я ошибаюсь):

\ 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; они должны соответствовать отдельным правилам escape-символов.

Десятичное число 255 равно Окталу 377 (используйте Windows Calculator в научном режиме для подтверждения)

Следовательно, трехзначное октальное значение попадает в диапазон от \000 (0) до \377 (255)

Следовательно, \4715 не является действительным восьмеричным значением, поскольку это правило больше трех восьмеричных цифр. Если вы хотите получить доступ к символу кодовой точки с десятичным значением 4715, используйте escape-символ 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:

Тип данных char (и, следовательно, значение этого объекта Character инкапсуляции) основаны на оригинальной спецификации Unicode, которая определенные символы как 16-битные объекты фиксированной ширины. Юникод с тех пор стандарт был изменен, чтобы учесть символы, чьи представление требует более 16 бит. Ассортимент юридического кодекса точки теперь от U + 0000 до U + 10FFFF, известные как скалярное значение Unicode. (См. Определение обозначения U + n в стандарте Unicode.)

Набор символов от U + 0000 до U + FFFF иногда называют как базовая многоязычная плоскость (BMP). Символы, чьи кодовые точки больше, чем U + FFFF, называются дополнительными символами. Ява 2 платформа использует представление UTF-16 в массивах символов и в Классы String и StringBuffer. В этом представлении дополнительные символы представлены в виде пары значений 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 #?
0 голосов
/ 10 сентября 2012

Я не знаю причин, по которым восьмеричные переходы ограничены кодовыми точками Юникода от 0 до 255. Это может быть по историческим причинам. Вопрос в основном останется без ответа, так как не было технической причины не увеличивать диапазон восьмеричных выходов при проектировании Java.

Следует отметить, однако, что существует не столь очевидная разница между побегами Юникода и восьмеричными побегами. Восьмеричные экранирования обрабатываются только как часть строк, в то время как экранирование unicode может происходить в любом месте файла, например, как часть имени класса. Также обратите внимание, что следующий пример даже не скомпилируется:

String a = "\u000A";

Причина в том, что \ u000A раскрывается до новой строки на очень ранней стадии (в основном при загрузке файла). Следующий код не генерирует ошибку:

String a = "\012";

\ 012 раскрывается после , когда компилятор проанализировал код. Это также относится и к другим выходам, таким как \ n, \ r, \ t и т. Д.

Итак, в заключение: экранирование в Юникоде НЕ является заменой восьмеричным экранированию. Это совершенно другая концепция. В частности, чтобы избежать каких-либо проблем (как в случае с \ u000A выше), следует использовать восьмеричное экранирование для кодовых точек от 0 до 255 и экранирование юникода для кодовых точек выше 255.

0 голосов
/ 03 марта 2012

Восьмеричные escape-числа \ 0- \ 377 также наследуются от C, и ограничение имеет смысл в таком языке, как C, где символы == байты (по крайней мере, в безмолвные дни до wchar_t).

...