В Java могут появиться сырые строковые литералы, и какие проблемы это может принести

Недавно на сайте OpenJDK появился черновик JEP, в котором предлагается ввести в язык новый вид литерала, называемый сырым строковым литералом. Такой литерал будет отличаться от традиционного строкового литерала тем, что в нём не будет экранирования специальных символов, и он может распространяться на несколько строк. Сырые строковые литералы будут заключаться в обратные одинарные кавычки (`) вместо двойных (").

Сырые строковые литералы уже существуют во многих языках (C++, C#, Scala, Python, Kotlin, Xtend …) и они являются действительно удобным инструментом, который неплохо было бы иметь и в Java. Их польза заключается в том, что при написании некоторых строк исчезает возня с экранированием символов и получается более читаемый код. Типичным примером такой проблемы являются регулярные выражения, в которых встречается множество метасимволов, требующих экранирования. Если же использовать сырые литералы, то вместо "\\w+\\s\\w+" получается `\w+\s\w+`.

Вторым мотиватором введения сырых строковых литералов является частая необходимость писать многострочные выражения: SQL-запросы, фрагменты скриптов, JSON и т.д. Сейчас для написания таких выражений используются обычные строковые литералы, находящихся на разных строках кода и объединённые с помощью оператора +. Сырые же литералы могут распространяться на несколько строк, поэтому с их помощью писать многострочные выражения будет намного удобнее.

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

Разные языки решают эту проблему по-разному. Например, Scala позволяет удалить лишние отступы в рантайме с помощью метода stripMargin(). В Haskell это решается с помощью сторонней библиотеки, использующей квазицитаты. Весьма интересным выглядит решение в языке Xtend, в котором на уровне компилятора реализована умная обработка отступов. Однако такое решение реализовано с помощью немалого количества магии внутри, что может запутать пользователей.

Тагир предлагает собственное решение: обязать начинать каждую новую строку литерала с символа |, который будет указывать начало строки, но при этом сам символ | не будет включён в строку. Это решит проблему форматирования и одновременно избавит от включения ненужных отступов в итоговую строку:

String query = `SELECT EMP_ID, LAST_NAME
               |FROM EMPLOYEES
               |WHERE CITY = 'Indianapolis'
               |AND AGE > 28
               |ORDER BY EMP_ID, LAST_NAME`

Предложение Тагира, возможно, не идеальное, но оно запустило дискуссию, которая должна завершиться принятием какого-то осмысленного решения со стороны архитекторов языка.

Подписывайтесь на канал в Telegram, чтобы не пропускать новости.

Все материалы на этом сайте выложены под лицензией CC BY-SA 4.0
© Евгений Козлов, 2017-2020