Escape символы java

Обновлено: 07.07.2024

Когда-то давно вы узнали, что чтобы записать в коде строку символов, нужно обернуть эти символы в двойные кавычки: получится строковой литерал .

А что делать, если нам нужно, чтобы кавычки были внутри строкового литерала? Строка, содержащая кавычки — что может быть проще.

Допустим, мы хотим вывести текст Фильм "Друзья" номинирован на "Оскар" . Как это сделать?

Код Примечания
Этот вариант работать не будет!

Все дело в том, что по мнению компилятора тут записан совсем другой код:

Код Примечания
Этот вариант работать не будет!

После того, как компилятор встретит двойные кавычки в коде, он будет считать их началом строкового литерала. Следующие двойные кавычки — окончанием строкового литерала.

Так как же записать в двойные кавычки внутри литерала?

2. Экранирование символов

Способ есть, ему даже дали название — экранирование символов . Вы просто пишете внутри строки текста кавычки, а перед кавычками добавляете символ \ ( обратная косая черта или обратный слеш или бекслеш , от англ. backslash ).

Вот как будет выглядеть правильно записанный строковой литерал:

Код Примечания
Это сработает!

Компилятор все поймет правильно и не будет считать кавычки, расположенные после обратной косой черты , обычными кавычками.

Более того, если вывести данную строку на экран, кавычки с обратной косой чертой будут правильно обработаны, и на экран будет выведена надпись без обратной косой черты: Фильм "Друзья" номинирован на "Оскар"

Еще важный момент. Кавычки, предваренные обратной косой чертой — это один символ: мы просто пользуемся таким хитрым способом записи, чтобы не мешать компилятору распознавать строковые литералы в коде. Вы можете присвоить кавычки в переменную char :

Код Примечания
\" — это один символ, а не два
так тоже можно: двойная кавычка внутри одинарных кавычек

Кодировка Unicode



Знаете ли вы, что следующее является допустимым выражением Java?

Вы можете попробовать скопировать и вставить его в основной метод любого класса и скомпилировать. Если вы затем добавите следующий оператор

и после компиляции запустите этот класс, код напечатает число 8!

А знаете ли вы, что этот комментарий вместо этого вызывает синтаксическую ошибку во время компиляции?

Тем не менее, комментарии не должны приводить к синтаксическим ошибкам. Фактически, программисты часто комментируют фрагменты кода, чтобы компилятор их игнорировал. так что же происходит?

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

Примитивный тип данных char

Как всем известно, char это один из восьми примитивных типов Java. Это позволяет нам хранить по одному символу. Ниже приведен простой пример, в котором значение символа присваивается типу char :

На самом деле этот тип данных используется нечасто, потому что в большинстве случаев программистам нужны последовательности символов и поэтому они предпочитают строки. Каждое буквальное значение символа должно быть заключено между двумя одинарными кавычками, чтобы не путать с двойными кавычками, используемыми для строковых литералов. Объявление строки:

Есть три способа присвоить литералу значение типа char , и все три требуют включения значения в одинарные кавычки:

используя один печатный символ на клавиатуре (например '&' ).

используя формат Unicode с шестнадцатеричной нотацией (например, '\u0061' , который эквивалентен десятичному числу 97 и идентифицирует символ 'a' ).

используя специальный escape-символ (например, '\n' который указывает символ перевода строки).

Давайте добавим некоторые детали в следующих трех разделах.

Печатаемые символы клавиатуры

Мы можем назначить любой символ, найденный на нашей клавиатуре, char переменной, при условии, что наши системные настройки поддерживают требуемый символ и что этот символ доступен для печати (например, клавиши «Canc» и «Enter» не печатаются).

В любом случае литерал, присваиваемый примитивному типу char , всегда заключен между двумя одинарными кавычками. Вот некоторые примеры:

Тип данных char хранится в 2 байтах (16 бит), а диапазон состоит только из положительных чисел от 0 до 65 535. Фактически, существует «отображение», которое связывает определенный символ с каждым числом. Это отображение (или кодирование) определяется стандартом Unicode (более подробно описанным в следующем разделе).

Формат Unicode (шестнадцатеричное представление)

Мы можем напрямую присвоить Unicode char значение в шестнадцатеричном формате, используя 4 цифры, которые однозначно идентифицируют данный символ, добавляя к нему префикс \u (всегда в нижнем регистре). Например:

В данном случае мы говорим о литерале в формате Unicode (или литерале в шестнадцатеричном формате). Фактически, при использовании 4 цифр в шестнадцатеричном формате охватывается ровно 65 536 символов.

Java 15 поддерживает Unicode версии 13.0, которая содержит намного больше символов, чем 65 536 символов. Сегодня стандарт Unicode сильно изменился и теперь позволяет нам представлять потенциально более миллиона символов, хотя уже присвоено только 143 859 чисел конкретным символам. Но стандарт постоянно развивается. В любом случае, для присвоения значений Unicode, выходящих за пределы 16-битного диапазона типа char , мы обычно используем классы вроде String и Character , но поскольку это очень редкий случай и не интересен для целей этой статьи, мы не будем об этом говорить.

Специальные escape-символы

В char типе также можно хранить специальные escape-символы, то есть последовательности символов, которые вызывают определенное поведение при печати:

\b эквивалентно backspace, отмене слева (эквивалентно клавише Delete).

\n эквивалентно переводу строки (эквивалентно клавише Ente).

\\ равняется только одному \ (только потому, что символ \ используется для escape-символов).

\t эквивалентно горизонтальной табуляции (эквивалентно клавише TAB).

\' эквивалентно одинарной кавычке (одинарная кавычка ограничивает литерал символа).

\" эквивалентно двойной кавычке (двойная кавычка ограничивает литерал строки).

\r представляет собой возврат каретки (специальный символ, который перемещает курсор в начало строки).

\f представляет собой подачу страницы (неиспользуемый специальный символ, представляющий курсор, перемещающийся на следующую страницу документа).

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

что эквивалентно следующему коду:

правильно и напечатает символ двойной кавычки:

Если бы мы попытались не использовать escape-символ для одиночных кавычек, например, со следующим утверждением:

мы получим следующие ошибки времени компиляции, поскольку компилятор не сможет различить разделители символов:

Поскольку разделители строковых литералов представлены в двойных кавычках, ситуация обратная. Фактически, внутри строки можно заключить одинарные кавычки:

С другой стороны, мы должны использовать \" escape-символ, чтобы использовать двойные кавычки в строке. Итак, следующее утверждение:

вызовет следующие ошибки компиляции:

Вместо этого верна следующая инструкция:

Написание Java кода в формате Unicode

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

Фактически, если мы добавим к предыдущей строке следующий оператор:

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

Формат Unicode для escape-символов

Тот факт, что компилятор преобразует шестнадцатеричный формат Unicode перед оценкой кода, имеет некоторые последствия и оправдывает существование escape-символов. Например, давайте рассмотрим символ перевода строки, который можно представить с помощью escape-символа \n . Теоретически перевод строки связан в кодировке Unicode с десятичным числом 10 (что соответствует шестнадцатеричному числу A). Но, если мы попытаемся определить его в формате Unicode:

мы получим следующую ошибку времени компиляции:

В реальности, компилятор преобразует предыдущий код в следующий перед его оценкой:

Формат Unicode был преобразован в символ новой строки, и предыдущий синтаксис не является допустимым синтаксисом для компилятора Java.

Аналогично, символ одинарной кавычки ' , который соответствует десятичному числу 39 (эквивалентно шестнадцатеричному числу 27) и который мы можем представить с помощью escape-символа \', не может быть представлен в формате Unicode:

Также в этом случае компилятор преобразует предыдущий код следующим образом:

что приведет к следующим ошибкам времени компиляции:

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

Также есть проблемы с символом возврата каретки, представленным шестнадцатеричным числом D (соответствующим десятичному числу 13) и уже представленным с помощью escape-символа \r . Фактически, если мы напишем:

мы получим следующую ошибку времени компиляции:

Фактически, компилятор преобразовал число в формате Unicode в возврат каретки, вернув курсор в начало строки, и то, что должно было быть второй одинарной кавычкой, стало первой.

Что касается символа , , представленного десятичным числом 92 (соответствующего шестнадцатеричному числу 5C) и представленного escape-символом \ , если мы напишем:

мы получим следующую ошибку времени компиляции:

Это потому, что предыдущий код будет преобразован в следующий:

и поэтому пара символов ' рассматривается как escape-символ, соответствующий одинарной кавычке, и поэтому в буквальном закрытии отсутствует другая одинарная кавычка.

С другой стороны, если мы рассмотрим символ " , представленный шестнадцатеричным числом 22 (соответствующий десятичному числу 34) и представленный escape-символом " , если мы напишем:

проблем не будет. Но если мы используем этот символ внутри строки:

мы получим следующую ошибку времени компиляции:

поскольку предыдущий код будет преобразован в следующий:

Тайна ошибки комментария

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

Это связано с тем, что компилятор всегда преобразует шестнадцатеричные форматы с помощью символов перевода строки и возврата каретки, которые несовместимы с однострочными комментариями; они печатают символы вне комментария!

Чтобы разрешить ситуацию, используйте обозначение многострочного комментария, например:

Другая ошибка, из-за которой программист может потерять много времени, - это использование последовательности \u в комментарии. Например, со следующим комментарием мы получим ошибку времени компиляции:

Если компилятор не находит допустимую последовательность из 4 шестнадцатеричных символов после \u , он выведет следующую ошибку:

Выводы

В этой статье мы увидели, что использование типа char в Java скрывает некоторые действительно удивительные особые случаи. В частности, мы увидели, что можно писать код Java, используя формат Unicode. Это связано с тем, что компилятор сначала преобразует формат Unicode в символ, а затем оценивает синтаксис. Это означает, что программисты могут находить синтаксические ошибки там, где они никогда не ожидали, особенно в комментариях.

Примечание автора: эта статья представляет собой короткий отрывок из раздела 3.3.5 «Примитивные символьные типы данных» тома 1 моей книги «Java для пришельцев». Для получения дополнительной информации посетите сайт книги (вы можете загрузить раздел 3.3.5 из области «Примеры»).


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

Большинство символов можно просто набрать с клавиатуры и использовать в коде PHP в их исходном виде. Например, $string = "php.watch" - это полностью допустимая строка в PHP, а $num = 42 - допустимое число. Также можно использовать многобайтные символы (для хранения которых требуется более одного байта), например, этот совершенно допустимый эмодзи: $emoji = "?" .

PHP, наряду со многими другими языками программирования, поддерживает определенное количество escape-последовательностей для использования различных символов, которые не могут быть набраны с обычной клавиатуры, не могут быть представлены в текстовой форме (например, невидимые символы или различные управляющие символы) или иным образом не считываются. Эти символы используют escape-последовательности, которые распознает PHP.

Что касается чисел, PHP поддерживает стандартные десятичные числа, но также может использовать и другие нотиции, такие как двоичное, восьмеричное, шестнадцатеричное и даже научное (scientific) представление. Они могут сделать код более читаемым и понятным в зависимости от контекста.

Двойные кавычки и Heredoc

В PHP строка с двойными кавычками ( "string" ) или Heredoc (смотрите ниже) поддерживает escape-последовательности и интерполяцию переменных.

PHP будет пытаться интерполировать переменные, если строковый литерал находится внутри строки с двойными кавычками или Heredoc.

Альтернативно (и желательно) интерполируемые переменные могут быть выделены фигурными скобками, так они будут выглядеть более удобочитаемыми:

Строки в одинарных кавычках ( 'string' ) и синтаксис Nowdoc не интерполируют переменные:

Только строки в двойных кавычках и Heredoc поддерживают escape-символы.

Экранирование символов

Поскольку PHP интерпретирует и интерполирует специальные символы внутри строковых литералов в двойных кавычках и heredoc, знак обратной косой черты ( \ ) используется как «escape-символ».

Например, использование \$name вместо $name не даст PHP интерполировать переменную $name .

Использование второго символа обратной косой черты предотвращает преобразование первого символа обратной косой черты в escape-символ.

PHP поддерживает несколько специальных escape-последовательностей для специальных символов. В приведенном выше примере \$ считается escape-последовательностью, потому что он отменяет интерполяцию PHP, заставляя PHP буквально использовать символ $ .

Символы табуляции: \t и \v

Возможно, самые простой из управляющих символов - это символ табуляции. Символ табуляции (по нажатию клавиши tab) можно использовать внутри строкового литерала, но использование \t вместо визуального пропуска делает его наглядным. Использование \t вместо буквального символа табуляции также позволяет избежать автоматической замены символов табуляции на пробелы в различных IDE.

\v - это вертикальная табуляция. На поддерживаемых терминалах символ вертикальной табуляции переходит к следующему символу в следующей строке:

Новые строки: \r и \n

\r («возврат каретки») и \n («перевод строки») являются символами новой строки.

Исторически так сложилось, что различные системы начали использовать либо \r , либо \n , и даже Windows использует \r\n . Например, Linux и MacOS по умолчанию используют символ «перевода строки» ( \n ) в качестве символа новой строки, тогда как Windows использует комбинацию \r\n (возврат каретки, за которым следует перевод строки). Старые системы MacOS использовали в качестве символа новой строки \r .

PHP имеет константу PHP_EOL , которая всегда ссылается на системный символ новой строки.

Escape-символ: \e

Escape-символы часто используется для отправки управляющих последовательностей ANSI в терминал. Например, \e , за которым следует [32m , указывает терминалу изменить цвет на зеленый, а [33m - на желтый.

Если приведенный выше фрагмент выполняется в терминале, который поддерживает управляющие последовательности ANSI, он интерпретирует его и изменяет текст:


Символ новой страницы: \f

Символ новой страницы - это управляющий символ ASCII для обозначения конца страницы. С его помощью принтеры могут вывести текущую страницу и начать с верхней части следующей. Когда \f передается на дисплейный терминал, он может результировать в очистке экрана, хотя это очень редкое поведение для большинства программ эмуляции терминала.

Восьмеричные escape-последовательности символов ASCII

PHP поддерживает экранирование восьмеричного числа в его соответствующий ASCII символ.

Например, ASCII символ P равен 80 в десятичной системе (смотрите диаграмму). 80 из десятичной системы счисления в переводе в восьмеричную - 120 .

Для символа P можно использовать восьмеричную escape-последовательность:

Любой базовый символ ASCII можно представить с помощью такой записи:

Любое значение в диапазоне от \0 до \377 будет интерпретироваться как восьмеричная escape-последовательность ASCII символа.

Обратите внимание, что числа для расширенных символов ASCII (от 128 до 255) несовместимы с UTF-8. PHP считает значение 128 (восьмеричное: 200 ; шестнадцатеричное: 80 ) недопустимым, поскольку оно не является допустимым значением UTF-8.

Хотя PHP принимает такие значения, они считаются недопустимыми символами в контексте UTF-8.

Шестнадцатеричные escape-последовательности символов ASCII

Подобно восьмеричным escape-последовательностям символов, PHP также допускает использование шестнадцатеричных чисел в escape-последовательности символов с префиксом \x .

Допускается только один байт, что подразумевает допустимый диапазон от x0 до xFF . Однако ограничение UTF-8 по-прежнему присутствует, и только значения до x80 будут считаться допустимыми символами.

Кроме того, шестнадцатеричные символы не чувствительны к регистру (т.е. AF равно af и aF ).

ASCII P - 80, что равно x50 :

Тот же "PHP.Watch" пример можно переписать с помощью шестнадцатеричных escape-последовательностей:

Escape-последовательности символов Unicode

PHP поддерживает использование любого Unicode символа с префиксом \u и шестнадцатеричным значением code point внутри фигурных скобок.

PHP выдаст ошибку парсера, если символ Unicode превышает значение 10FFFF :

10FFFF является верхним пределом, потому что спецификация UTF-8 объявляет диапазон от U+0000 до U+10FFFF .

В предыдущей версии этой статьи верхний предел неверно упоминался как FFFFF , что было исправлено на 10FFFF . Спасибо Саре Големон за то, что она указала на это.

Форму записи Unicode \u<> можно использовать качестве escape-последовательности для любого символа. Вот несколько примеров:

4. Кодировка Unicode

Как вы уже знаете, каждому символу, отображаемому на экране, соответствует определенный числовой код. Стандартизированный набор таких кодов называют кодировкой .

ASCII (англ. American Standard Code for Information Interchange) — американская стандартная кодировочная таблица для печатных символов и некоторых специальных кодов.

Она состояла из 33 непечатных управляющих символов (влияющих на обработку текста и пробелов) и 95 печатных символов, включая цифры, буквы латинского алфавита в строчном и прописном вариантах и ряд пунктуационных символов.

Кодировка Unicode

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

Со временем появилась идея: создать одну кодировку, в которой разместить все символы всех мировых кодировок.

Кодировка Unicode 1

В 1993 году была создана кодировка Unicode , и язык Java был первым языком программирования, который использовал ее как стандарт хранения текста. Сейчас же Unicode — стандарт всей ИТ-индустрии.

И хотя Unicode сам по себе является стандартом, у него есть несколько форм представления (Unicode transformation format, UTF): UTF-8, UTF-16 и UTF-32, и пр.

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

Чтобы записать в коде программы символ кодировки Unicode по его коду, нужно написать \u + шестнадцатеричные цифры кода . Например \u00A9

Код Примечания
Этот вариант работать не будет!

Код Примечания
Этот вариант работать не будет!

Код Примечания
Это сработает!

Код Примечания
\" — это один символ, а не два
так тоже можно: двойная кавычка внутри одинарных кавычек

Часто возникающие ситуации при экранировании символов


Код Вывод на экран

Код Описание
\t Вставить символ табуляции
\b Вставить символ возврата на один символ
\n Вставить символ новой строки
\r Вставить символ возврата каретки
\f Вставить символ прогона страницы
\' Вставить одинарную кавычку
\" Вставить двойную кавычку
\\ Вставить обратный слеш

Символ табуляции – \t

Данный символ в тексте эквивалентен нажатию на клавиатуре клавиши Tab при наборе текста. Он сдвигает следующий за ним текст с целью его выровнять.

Код Вывод на экран

Возврат на один символ назад – \b

Данный символ в тексте эквивалентен нажатию на клавиатуре клавиши Backspace при наборе текста. Он удаляет последний выведенный символ перед ним:

Код Вывод на экран

Символ возврата каретки – \r

Этот символ переносит курсор в начало текущей строки, не меняя текста. Следующий выводимый текст будет перетирать существующий.

Код Вывод на экран
Мир!

Символ прогона страницы – \f

Это символ дошел до нас из эпохи первых матричных принтеров. Если подать такой символ на печать, это приводило к тому, что принтер просто прокручивал текущий лист, не печатая текст, пока не начнется новый.

Сейчас бы мы назвали его разрыв страницы или новая страница .

Ну а тут вообще все просто. Если мы используем обратную косую черту (обратный слэш) в тексте, чтобы экранировать символы, то как тогда записать в текстовой строке сам символ косой черты?

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

Код Вывод на экран
Компилятор будет ругаться на неизвестные экранированные символы.
Вот так правильно!

В классе Solution замени все короткие имена классов в коде на полные.

3. Часто возникающие ситуации при экранировании символов

Часто возникающие ситуации экранирования символов

Кроме двойных кавычек, есть еще много символов, которые по-особому обрабатываются компилятором. Например, перенос строки.

Как добавить в литерал перенос строки? Для этого тоже есть специальная комбинация:

Код Вывод на экран

Всего таких специальных комбинаций 8: их еще называют escape-последовательностями , вот они:

Код Описание
\t Вставить символ табуляции
\b Вставить символ возврата на один символ
\n Вставить символ новой строки
\r Вставить символ возврата каретки
\f Вставить символ прогона страницы
\' Вставить одинарную кавычку
\" Вставить двойную кавычку
\\ Вставить обратный слеш

С двумя из них вы познакомились, а что значат остальные 6?

Данный символ в тексте эквивалентен нажатию на клавиатуре клавиши Tab при наборе текста. Он сдвигает следующий за ним текст с целью его выровнять.

Код Вывод на экран

Данный символ в тексте эквивалентен нажатию на клавиатуре клавиши Backspace при наборе текста. Он удаляет последний выведенный символ перед ним:

Код Вывод на экран

Этот символ переносит курсор в начало текущей строки, не меняя текста. Следующий выводимый текст будет перетирать существующий.

Код Вывод на экран

Это символ дошел до нас из эпохи первых матричных принтеров. Если подать такой символ на печать, это приводило к тому, что принтер просто прокручивал текущий лист, не печатая текст, пока не начнется новый.

Сейчас бы мы назвали его разрыв страницы или новая страница .

Ну а тут вообще все просто. Если мы используем обратную косую черту (обратный слэш) в тексте, чтобы экранировать символы, то как тогда записать в текстовой строке сам символ косой черты?

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

Код Вывод на экран
Компилятор будет ругаться на неизвестные экранированные символы.
Вот так правильно!

Выведи на экран следующий текст в две строки: It's Windows path: "C:\Program Files\Java\jdk-13.0.0\bin" It's Java string: \"C:\\Program Files\\Java\\jdk-13.0.0\\bin\" Подсказка: \” – экранирование двойной кавычки; \\ – экранирование обратной косой черты (\). Больше про экранирование символов и Esca

Читайте также: