Рубрики
Без рубрики

Текстовые блоки Java 13 – Многострочные строковые литералы

Java 13 наконец-то обеспечивает поддержку многострочных строковых литералов после отказа от аналогичной функциональности fr… Помеченный java.

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

Строковые литералы в Java

Объявить строковый литерал в Java несложно:

String myString = "Behold, a string literal!";

Ничего нового, верно? Однако традиционные строковые литералы имеют некоторые неудобные ограничения.

Прежде всего, весь литерал должен находиться всего в одной строке. Это нормально для простых коротких строк, но для более длинных вам нужно прибегнуть к объединению нескольких строковых литералов. Если вы хотите также включить разрывы строк, вам нужно добавить \n .

String myString = "This is my string\n" +
        "which I want to be \n" +
        "on multiple lines.";

Это громоздко и трудно читаемо. Другая проблема заключается в том, что различные символы не могут быть представлены напрямую, но их необходимо экранировать, например " или \ . Это делает ваши строки еще более трудными для чтения и работы с ними.

String path = "Open \"C:\\Program Files\\Java\\jdk1.8.0_152\"";

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

Другие языки JVM

Как обычно, Java опаздывает с внедрением функциональности, которая уже распространена во многих других языках, даже на JVM. Kotlin, Scala или Groovy уже поддерживают многострочные строковые литералы, использующие """ обозначения вместо обычных " . Посмотрите на следующий пример в Kotlin.

val text = """
This is my cool string,
which I want to span
multiple lines.
It can have backslash \
and even double-quotes "
"""

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

Необработанные строковые литералы в Java

В Java 12 изначально предлагалось включить Необработанные строковые литералы (JEP-326) . Поведение было очень похоже на приведенный выше пример в Kotlin. Но вместо использования """" , как в других языках JVM, в нем использовалась обратная нотация. Концепция была немного необычной в том смысле, что вы могли использовать любое количество обратных ссылок и такое же количество обратных ссылок в конце. Таким образом, не было необходимости экранировать обратные метки внутри литерала spring, независимо от того, сколько последовательных обратных меток присутствовало.

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

public static void main(String[] args) {
      String myString =
      `This is my string
      which I want to be
      on multiple lines.`;
      System.out.println(myString);
  }

Если вы распечатаете его, то во всех строках, кроме первой, будут присутствовать отступы.

This is my string
        which I want to be
        on multiple lines.

Вам нужно будет исправить это вручную, возможно, с помощью недавно предложенных строковых методов align() и отступ() . Не очень практично, но это то, с чем вам пришлось бы смириться, если бы вы использовали необработанные строки.

Вы можете прочитать больше об исходном предложении необработанных строковых литералов в следующей статье :

Однако это предложение было отклонено до окончательного выпуска Java 12 и в настоящее время считается устаревшим.

В то время как мы можем ожидать, что для любой языковой функции будет нетривиальный объем отзывов “Я бы предпочел это по-другому”, анализируя отзывы, которые мы получили, я больше не уверен, что мы все еще достигли правильного набора компромиссов между сложностью и выразительностью, или что мы достигли изучили достаточно дизайнерского пространства, чтобы быть уверенными, что текущий дизайн – это лучшее, что мы можем сделать. Отказавшись, мы можем продолжить доработку дизайна, изучить дополнительные варианты и стремиться к предварительному просмотру, который действительно соответствует требованиям процесса предварительного просмотра функций (JEP 12).

Многострочные строковые литералы в Java

После отзыва первоначального предложения обсуждение было возобновлено и привело к совершенно новому предложению, которое будет представлено в Java 13 в качестве функции предварительного просмотра. Он называется JEP 355: Текстовые блоки (предварительный просмотр) .

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

Функция предварительного просмотра

Текстовые блоки будут доступны только в качестве функции предварительного просмотра в Java 13. Что это значит?

Язык предварительного просмотра или функция виртуальной машины – это новая функция платформы Java SE, которая полностью определена, полностью реализована и в то же время непостоянна. Он доступен в выпуске функций JDK, чтобы вызвать обратную связь разработчиков, основанную на реальном использовании; это может привести к тому, что он станет постоянным в будущей платформе Java SE.

Перед следующим выпуском функций JDK будут оценены сильные и слабые стороны функций “реального мира”, чтобы решить, играет ли функция долгосрочную роль в платформе Java SE, и если да, то нуждается ли она в доработке. Следовательно, функции может быть присвоен окончательный и постоянный статус (с уточнениями или без них), или пройти дополнительный период предварительного просмотра (с уточнениями или без них), или же быть удалена.

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

Вам нужно будет загрузить JDK 13 . В IntelliJ перейдите в File = Project Structure и убедитесь, что у вас выбран JDK13 в разделе Project SDK. Чтобы включить текстовые блоки в качестве функции предварительного просмотра, обязательно выберите 13 (Предварительный просмотр) - Текстовые блоки в разделе Уровень языка проекта .

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

javac --release 13 --enable-preview ...

Это для времени компиляции. Во время выполнения вы просто предоставляете --enable-preview

java --enable-preview ...

Текстовые блоки

В отличие от отклоненных необработанных строковых литералов, текстовые блоки заключены в три двойные кавычки """" , такие же, как в Groovy или Kotlin. Это больше согласуется с обычными строковыми литералами и другими языками JVM.

String myBlock = """
                  line 1
                  line 2
                  line 3
                  """

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

Обработка

В отличие от обычных строковых литералов, текстовые блоки обрабатываются компилятором в три этапа:

  1. Концы линии нормализуются
  2. Лишние пробелы удаляются
  3. Экранированные символы интерпретируются

Нормализация конца строки

Операционные системы на базе Windows и UNIX имеют разные символы для обозначения окончаний строк.

Windows использует возврат каретки \r и Перевод строки \n , в то время как системы на базе Unix используют только перевод строки. Проблема в том, что текстовые блоки используют символы новой строки непосредственно из исходного кода, вместо использования \n , таких как обычные строковые литералы. Это означает, что исходный код, созданный в Unix, будет содержать строки с разными окончаниями строк при компиляции в Windows. Строки выглядели бы идентично невооруженным глазом, но имели бы разные окончания строк.

Чтобы предотвратить это, компилятор Java принимает все окончания строк в текстовых блоках и нормализует их до перевода строки \n . Важно то, что это делается перед вычислением экранированных символов. Это означает, что если вам явно необходимо включить возврат каретки с помощью \r , вы можете это сделать, поскольку он вычисляется после нормализации окончания строки и не будет затронут.

Удаление вмятин

Помните пример с необработанными строковыми литералами и отступами? Необработанные строковые литералы интерпретируют все символы, включая отступы. Таким образом, пробелы, которые должны были просто облегчить чтение вашего исходного кода, на самом деле становятся частью ваших строк. В подавляющем большинстве случаев это нежелательное поведение.

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

  • Все конечные пробелы удаляются из конца строк.
  • Начальный общий пробел удаляется из начала каждой строки.

Что именно это означает? Давайте посмотрим на следующий код:

public static void main(String[] args) {
    String html = """
                  
                    
                      

Hello, world

"""; }

Фрагмент HTML-кода содержит много пробелов, но на самом деле он ему не принадлежит. Это просто делает его хорошо выровненным в исходном файле. Что важно, так это относительный отступ внутри блока.

Другими словами: если каждая строка в фрагменте начинается с 22 пробелов, мы можем их игнорировать. Эти 22 пробела представляют собой общий префикс пробела , который можно игнорировать, и следует сохранить только то, что находится поверх него.

Давайте заменим общий префикс на . . Все эти пробелы будут отброшены. Будут сохранены только пробелы, отмеченные символом - , поскольку они превышают общий префикс пробела.

String html = """
..............
..............--
..............----

Text Blocks are awesome!

..............-- .............. ..............""";

Результатом будет:


  
    

Text Blocks are awesome!

Обратите внимание, что на этом шаге удаляются только прямые пробелы. Если у вас есть пробелы в виде экранированных символов, таких как \n или \t , они не будут удалены.

Спасаясь

Текстовые блоки не являются необработанными строками, и вы все равно можете использовать экранирование. Однако вам не нужно беспокоиться о самых распространенных из них.

  • Новая строка \n больше не нужна, поскольку текстовые блоки по своей природе многострочны.
  • Вам не нужно экранировать " двойные кавычки, поскольку они больше не отмечают окончание строкового литерала
String myBlock = """
                 First line
                 Second Line with " quotes
                 """

Поскольку цитирование разрешено, технически вы можете включить \n и \" , но это не обязательно и не рекомендуется. Вам все равно нужно избегать косой черты \\ . Но в целом текстовые блоки требуют гораздо меньшего экранирования, чем старые добрые строковые литералы. Все escape-последовательности, которые могут быть использованы в строковых литералах, также могут быть использованы для текстовых блоков. Проверьте Java spec для получения полного списка.

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

Новые Строковые методы

В рамках предложения по текстовым блокам появились три новых метода класса String .

  1. translate Escapes() – преобразует escape-последовательности в строке, за исключением символов unicode.
  2. strip Indent() – удаляет общие пробелы из начала каждой строки.
  3. отформатированный(Объект... аргументы) – Удобный метод, эквивалент String.format(строка, аргументы)

Вывод

  • Текстовые блоки предлагают удобный способ работы с многострочными строковыми литералами.
  • Чтобы создать текстовый блок, просто окружите свою строку символом """" .
  • Вы можете использовать текстовые блоки в любом месте, где вы можете использовать строковые литералы
  • Окончания строк нормализуются до НЧ
  • Лишние пробелы удаляются с начала и конца каждой строки. Сохраняется только относительный отступ.
  • Это функция предварительного просмотра в Java 13, которая должна быть явно включена
  • Предложение о необработанных строковых литералах было изъято из Java 12; вместо этого позже были введены текстовые блоки

Оригинал: “https://dev.to/vojtechruz/java-13-text-blocks-6nb”