Почему некоторые символьные литералы вызывают ошибки синтаксиса в Java?

В последнем выпуске бюллетеня JavaSpecialists автор упоминает фрагмент кода, который не компилируется в Java

public class A1 {
  Character aChar = '\u000d';
}

Попробуйте скомпилировать его, и вы получите сообщение об ошибке, например:

A1.java:2: illegal line end in character literal
              Character aChar = '\u000d';
                                ^

Почему эквивалентная часть кода С# не показывает такую ​​проблему?

public class CharacterFixture
{
  char aChar = '\u000d';
}

Я что-то пропустил?

EDIT: Мое первоначальное намерение вопроса заключалось в том, как компилятор С# получил правильное синтаксическое разборчивание файла Unicode (если это так) и почему java все равно должен придерживаться неправильного (если так) разбора? EDIT: Также я хочу, чтобы вопрос о миоригинальном вопросе был восстановлен? Почему такое тяжелое редактирование, и я сильно подозреваю, что он сильно изменил мои намерения.

Ответы

Ответ 1

Компилятор Java переводит \uxxxx escape-последовательности как один из первых шагов, даже до того, как токенизатор получает трещину в коде. К тому времени, когда он фактически начинает токенизацию, больше нет \uxxxx; они уже превращены в символы, которые они представляют, поэтому для компилятора ваш пример Java выглядит так же, как если бы вы каким-то образом набрали возврат каретки. Он делает это, чтобы обеспечить способ использования Unicode в источнике, независимо от кодировки исходного файла. Даже текст ASCII может по-прежнему полностью отображать символы Unicode, если это необходимо (за счет удобочитаемости), а так как это сделано так рано, вы можете получить их почти в любом месте кода. (Вы могли бы сказать \u0063\u006c\u0061\u0073\u0073\u0020\u0053\u0074\u0075\u0066\u0066\u0020\u007b\u007d, и компилятор прочитал бы его как class Stuff {}, если бы вы хотели раздражать или мучить себя.)

С# этого не делает. \uxxxx переводится позже, с остальной частью программы, и действителен только в определенных типах токенов (а именно, для идентификаторов и литералов string/char). Это означает, что он не может использоваться в определенных местах, где он может использоваться на Java. cl\u0061ss не является ключевым словом, например.