Почему Java допускает экранированные символы Юникода в исходном коде?

Недавно я узнал, что Unicode разрешен в исходном коде Java не только как символы Unicode (например, double π = Math.PI;), но также как экранированные последовательности (например, double \u03C0 = Math.PI;).

Первый вариант имеет смысл для меня - он позволяет программистам называть переменные и методы на международном языке по своему выбору. Однако я не вижу практического применения второго подхода.

Вот несколько фрагментов кода, иллюстрирующих использование, протестированных с Java SE 6 и NetBeans 6.9.1:

Этот код распечатает 3.141592653589793

public static void main(String[] args) {
    double π = Math.PI;
    System.out.println(\u03C0);
}

Объяснение: π и \u03C0 - это один и тот же символ Unicode

Этот код ничего не распечатывает

public static void main(String[] args) {
    double π = Math.PI; /\u002A
    System.out.println(π);

    /* a comment */
}

Пояснение: код выше фактически кодирует:

public static void main(String[] args) {
    double π = Math.PI; /*
    System.out.println(π);

    /* a comment */
}

Который комментирует печатный текст.

Только из моих примеров я заметил ряд потенциальных проблем с этой языковой функцией.

Во-первых, плохой программист может использовать его, чтобы тайно закомментировать биты кода или создать несколько способов идентификации одной и той же переменной. Возможно, есть и другие ужасные вещи, о которых я не мог подумать.

Во-вторых, кажется, что не хватает поддержки среди IDE. Ни NetBeans, ни Eclipse не предоставили правильную подсветку кода для примеров. Фактически, NetBeans даже отмечал синтаксическую ошибку (хотя компиляция не была проблемой).

Наконец, эта функция плохо документирована и не является общепринятой. Зачем программисту использовать в своем коде что-то, что другие программисты не смогут распознать и понять? На самом деле, я даже не смог найти что-то об этом в вопросе о скрытых функциях Java.

У меня вопрос такой:

Почему Java позволяет использовать в синтаксисе экранированные последовательности Unicode? Каковы некоторые "плюсы" этой функции, которые позволили ей остаться частью Java, несмотря на ее многочисленные "минусы"?

5 ответов

Решение

Экранирующие последовательности Unicode позволяют хранить и передавать исходный код в чистом ASCII-коде и по-прежнему использовать весь диапазон символов Unicode. Это имеет два преимущества:

  • Нет риска того, что символы не ASCII могут быть повреждены инструментами, которые не могут их обработать. Это было серьезной проблемой еще в начале 1990-х годов, когда была разработана Java. Отправка электронного письма, содержащего символы, не входящие в ASCII, и его поступление без изменений - скорее исключение, чем норма.

  • Нет необходимости указывать компилятору и редактору /IDE, какую кодировку использовать для интерпретации исходного кода. Это все еще очень актуальная проблема. Конечно, гораздо лучшим решением было бы иметь кодировку в виде метаданных в заголовке файла (как в XML), но тогда это еще не стало лучшей практикой.

Первый вариант имеет смысл для меня - он позволяет программистам называть переменные и методы на международном языке по своему выбору. Однако я не вижу практического применения второго подхода.

Оба приведут к тому же байт-коду и имеют ту же мощность, что и языковая функция. Разница лишь в исходном коде.

Во-первых, плохой программист может использовать его, чтобы тайно закомментировать биты кода или создать несколько способов идентификации одной и той же переменной.

Если вы обеспокоены тем, что программист намеренно саботирует удобочитаемость вашего кода, эта языковая функция - наименьшая из ваших проблем.

Во-вторых, кажется, что не хватает поддержки среди IDE.

Это вряд ли вина функции или ее дизайнеров. Но тогда, я не думаю, что это когда-либо было предназначено, чтобы использоваться "вручную". В идеале в среде IDE можно было бы указать, чтобы вы вводили символы обычным образом и отображали их в обычном режиме, но автоматически сохраняли их как escape-последовательности Unicode. Возможно, уже есть плагины или параметры конфигурации, которые заставляют IDE вести себя таким образом.

Но в целом эта функция, по-видимому, используется очень редко и, вероятно, поэтому плохо поддерживается. Но как люди, которые разработали Java примерно в 1993 году, узнали об этом?

Хорошая вещь о \u03C0 Кодировка заключается в том, что текстовый редактор с неправильными настройками кодирования с гораздо меньшей вероятностью подвергается манипуляциям. Например, ошибка в моем программном обеспечении была вызвана случайным преобразованием из UTF-8 é в MacRoman é неправильно настроенным текстовым редактором. Определяя код Unicode, вы понимаете, что вы имеете в виду.

Синтаксис \uXXXX позволяет однозначно представлять символы Unicode в файле с кодировкой, не способной выражать их напрямую, или если вы хотите, чтобы представление гарантированно использовалось даже в самом низком общем знаменателе, а именно в 7-битной кодировке ASCII.

Вы можете представить все свои символы с помощью \uXXXX, даже пробелы и буквы, но это редко требуется.

Во-первых, спасибо за вопрос. Я думаю, что это очень интересно. Во-вторых, причина в том, что исходный файл Java представляет собой текст, который может использовать различные кодировки. Например, кодировка по умолчанию в Eclipse - Cp1255. Это окончание не поддерживает символы, такие как π. Я думаю, что они думали о программистах, которые должны работать на системах, которые не поддерживают Unicode, и хотели позволить этим программистам создавать программы с поддержкой Unicode. Это было причиной для поддержки нотации.

В спецификации языка указано, почему это разрешено . Могут быть и другие неустановленные причины, а также непредвиденные выгоды и последствия; но это дает прямой ответ на вопрос (выделено мной):

Необработанный поток символов Unicode преобразуется в последовательность токенов с использованием следующих трех шагов лексического преобразования, которые применяются по очереди:

  1. Преобразование экранирования Unicode (§3.3) в необработанном потоке символов Unicode в соответствующий символ Unicode. Экранирование Unicode в форме \uxxxx, где xxxx - шестнадцатеричное значение, представляет собой кодовую единицу UTF-16 с кодировкой xxxx. Этот шаг трансляции позволяет выразить любую программу, используя только символы ASCII.

...

Другие вопросы по тегам