Есть ли в Java способ написать строковый литерал без экранирования кавычек?


111

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

На некоторых языках вы можете просто сделать это:

foo = '"Hello, World"';

В Java, однако, ''используется для chars, поэтому вы не можете использовать его Stringтаким образом. В некоторых языках есть синтаксис, позволяющий обойти это. Например, в Python вы можете сделать так:

"""A pretty "convenient" string"""

Есть ли в Java что-нибудь подобное?



Этот ответ показывает, как вставить многострочные экранированные строки в Eclispe.
Джефф Аксельрод,

2
Обновление 2018: могут появиться необработанные строковые литералы для Java. Смотрите мой ответ ниже
VonC

затем System.out.println(mapperObj.writeValueAsString(mapperObj.readValue(str, Object.class)));
импортируйте объект Jackson ObjectMapper

обновление Q4 2018: необработанные строковые литералы пока не появятся. См. Мой обновленный ответ .
VonC

Ответы:


74

Ответ отрицательный, и доказательство содержится в Спецификации языка Java :

  StringLiteral:
   "StringCharacters"

  StringCharacters:
   StringCharacter
   | StringCharacters StringCharacter

  StringCharacter:
   InputCharacter but not " or \
   | EscapeSequence

Как видите, a StringLiteralможет быть просто привязан к "специальному символу и не может содержать его без экранирования.

Примечание: вы можете встроить Groovy в свой проект, это расширит синтаксис Java, позволяя вам использовать '''multi line string ''', ' "string with single quotes" 'а также "string with ${variable}".


141

Нет, и меня всегда раздражало отсутствие различных синтаксисов строковых литералов в Java.

Вот трюк, который я использовал время от времени:

String myString = "using `backticks` instead of quotes".replace('`', '"');

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


разве вам не нужно использовать replaceAll?
Landon Kuhn

10
@ landon9720 Нет, .replace заменяет все вхождения символа / последовательности символов другим символом / последовательностью символов. .replaceAll использует регулярное выражение.
abelito

Из любопытства знаете ли вы, упростит ли компилятор java это при компиляции?
ug_

2
Нет, я не думаю, что компилятор упростит это. Но это не имеет значения. Это очень недорогой вызов, и если я сделаю это только для статических конечных строк, затраты будут понесены только один раз при загрузке класса. Это цена, которую я обычно готов заплатить за более красивый код :)
Benjismith

3
Тогда как насчет "\" в myString?
Андерсон

10

Обновление декабрь 2018 г. (12 месяцев спустя):

Необработанные строковые литералы (которые находятся в желтом списке ) не попадут в JDK 12.
См. Критику здесь .


Может быть в будущей версии Java (10 или больше).

См. JEPS 8196004 от января 2018 г .: ( «JEP» - это «Программа расширения JDK» )

Проект JEP: необработанные строковые литералы

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

Так что вместо:

Runtime.getRuntime().exec("\"C:\\Program Files\\foo\" bar");
String html = "<html>\n"
              "    <body>\n" +
              "         <p>Hello World.</p>\n" +
              "    </body>\n" +
              "</html>\n";
System.out.println("this".matches("\\w\\w\\w\\w"));

Вы можете ввести:

Runtime.getRuntime().exec(`"C:\Program Files\foo" bar"`);
    
String html = `<html>
                   <body>
                       <p>Hello World.</p>
                   </body>
               </html>
              `;

System.out.println("this".matches(`\w\w\w\w`));

Ухоженная!

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


5

Простой ответ: нет.

Для более длинных строк, которые необходимо экранировать, я обычно читаю их с какого-то внешнего ресурса.


4

вы также можете использовать StringEscapeUtils из общего доступа Apache

ОБНОВЛЕНИЕ : Если кого-то интересуют некоторые примеры, вот полезная ссылка: https://dzone.com/articles/commons-lang-3-improved-and-powerful-StringEscapeUtils


2
Не могли бы вы добавить пример, основанный на вопросе, иллюстрирующем, как это сделать для этой проблемы?
Bengt

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

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

Связанный класс (org.apache.commons.lang3.StringEscapeUtils) устарел и заменен на org.apache.commons.text.StringEscapeUtils
jcarter

-4

Мне кажется, работает следующее:

String x = "Some Text" + '"' + "More Text" + '"' + "Even More Text";

Я думаю, потому что char - это примитивный тип переменной для String, Strings и chars могут быть объединены (по крайней мере, компилятор eclipse, похоже, не жалуется).


1
Я думаю, потому что char - это примитивный тип переменной для String <- Ваше предположение неверно. В этом отношении он также будет работать с другим типом, например int, например: String x = "Some text" + 33 + "More text";
Najeeb

-6

Если вы хотите экранировать 'или "в своей строке, вы можете использовать следующий код:

String text = ...

text = text.replaceAll("('|\")", "\\\\$1");

Вопрос о строковых литералах в исходном коде. Извините, попробуйте еще раз.
michaelb958 - GoFundMonica
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.