Подтвердить что ты не робот

Почему некоторые символы ASCII не могут быть выражены в форме "\ uXXXX" в исходном коде Java?

Я наткнулся на это (снова) сегодня:

class Test {
    char ok = '\n';
    char okAsWell = '\u000B';
    char error = '\u000A';
}

Он не компилируется:

Недопустимая символьная константа в строке 4.

Компилятор, похоже, настаивает на том, что вместо этого я пишу '\n'. Я не вижу причин для этого, но это очень раздражает.

Есть ли логическое объяснение, почему символы, которые имеют специальное обозначение (например, \t, \n, \r), должны быть выражены в этой форме в источнике Java?

4b9b3361

Ответ 1

Символы Unicode заменяются их значением, поэтому ваша строка заменяется компилятором:

char error = '
';

который не является допустимым оператором Java.

Это продиктовано Language Specification:

Компилятор для языка программирования Java ( "Java-компилятор" ) сначала распознает escape-коды Unicode в своем вводе, переводя символы ASCII\u, за которыми следуют четыре шестнадцатеричных цифры в кодовый блок UTF-16 (§ 3.1) указанного шестнадцатеричного значение и передача всех остальных символов без изменений. Представление дополнительных символов требует двух последовательных Unicode-экранов. Этот шаг перевода приводит к последовательности входных символов Unicode.

Это может привести к неожиданным вещам, например, это действительная программа Java (она содержит скрытые символы Unicode) - любезность Питера Лоури

public static void main(String[] args) {
    for (char c‮h = 0; c‮h < Character.MAX_VALUE; c‮h++) {
        if (Character.isJavaIdentifierPart(c‮h) && !Character.isJavaIdentifierStart(c‮h)) {
            System.out.printf("%04x <%s>%n", (int) c‮h, "" + c‮h);
        }
    }
}

Ответ 2

escape-последовательности Unicode, такие как \u000a, заменяются фактическими символами, которые они представляют, прежде чем компилятор Java сделает что-либо еще с исходным кодом. Итак, ваша программа в конечном итоге заканчивается на

char ch = '
';

Таким образом, \u000a в исходном коде заменяется внутренне символом перевода строки. Обратите внимание, что это происходит до того, как компилятор действительно прочитает и интерпретирует ваш исходный код.

Ссылаясь на Специфика языка Java:

Это ошибка времени компиляции для терминатора линии (§3.4), которая появляется после открытия "и до закрытия".

А также все знают наизусть, \n является ограничителем строк, цитируя:

 LineTerminator:
    the ASCII LF character, also known as "newline"
    the ASCII CR character, also known as "return"
    the ASCII CR character followed by the ASCII LF character

Другие символы, которые могут вызвать проблемы, например, \, ' и ".

Ответ 4

Это описано в 3.3. Unicode Escapes http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html. Javac сначала находит \uxxxx последовательности в .java и заменяет их реальными символами, затем компилирует. В случае

char error = '\u000A';

\ u000A будет заменен символьным кодом newline (10), и фактический текст будет

char error = '
';

Ответ 5

Потому что компилятор рассматривает их так же, как неэкранированный текст.

Это действительный код:

 class \u00C9 {}