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

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

Узнайте, как использовать функцию предварительного просмотра JDK 13/14 текстовых блоков Java.

Автор оригинала: Martin van Wingerden.

1. введение

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

В этом уроке мы увидим как использовать функцию предварительного просмотра текстовых блоков JDK 13/14 .

2. Использование

Начиная с Java 13, текстовые блоки доступны в качестве функции предварительного просмотра . Текстовые блоки начинаются с “”” (три двойные кавычки), за которыми следуют необязательные пробелы и новая строка. Самый простой пример будет выглядеть так:

String example = """
     Example text""";

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

Внутри текстовых блоков мы можем свободно использовать новые строки и кавычки без необходимости экранирования . Это позволяет нам включать буквальные фрагменты HTML, JSON, SQL или все, что нам нужно, более элегантным и читаемым способом.

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

3. Отступ

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

Рассмотрим текстовый блок, содержащий некоторый HTML:

public String getBlockOfHtml() {
    return """
            

                
                    example text
                
            """;
}

В этом случае минимальный отступ составляет 12 пробелов. Таким образом, все 12 пробелов слева от и на всех последующих строках удаляются. Давайте проверим это:

@Test
void givenAnOldStyleMultilineString_whenComparing_thenEqualsTextBlock() {
    String expected = "\n"
      + "\n" 
      + "    \n"
      + "        example text\n"
      + "    \n"
      + "";
    assertThat(subject.getBlockOfHtml()).isEqualTo(expected);
}

@Test
void givenAnOldStyleString_whenComparing_thenEqualsTextBlock() {
    String expected = "\n\n    \n        example text\n    \n";
    assertThat(subject.getBlockOfHtml())
       .isEqualTo(expected);
}

Когда нам нужен явный отступ , мы можем использовать меньший отступ для непустой строки (или последней строки):

public String getNonStandardIndent() {
    return """
                Indent
            """;
}

@Test
void givenAnIndentedString_thenMatchesIndentedOldStyle() {
    assertThat(subject.getNonStandardIndent())
            .isEqualTo("    Indent\n");
}

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

4. Побег

Внутри текстовых блоков двойные кавычки и новые строки не должны экранироваться. Однако мы можем использовать экранирование, чтобы добавить, например, возврат каретки ( \r ) или вкладки ( \t ) в текстовый блок. Мы даже можем снова использовать “”” в нашем текстовом блоке, избегая одной из двойных кавычек:

public String getTextWithEscapes() {
    return """
            fun with\n
            whitespace\t\r
            and other escapes \"""
            """;
}

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

Кроме того, обратите внимание, что даже если исходный файл имеет окончания строк Windows ( \r\n ), текстовые блоки будут заканчиваться только новыми строками ( \n ) . Если нам нужно, чтобы возвращаемые каретки ( \r ) присутствовали, мы должны явно добавить их в текстовый блок:

public String getTextWithCarriageReturns() {
    return """
            separated with\r
            carriage returns""";
}

@Test
void givenATextWithCarriageReturns_thenItContainsBoth() {
    assertThat(subject.getTextWithCarriageReturns())
            .isEqualTo("separated with\r\ncarriage returns");
}

5. Форматирование

Для облегчения подстановки переменных был добавлен новый метод, позволяющий вызывать метод String.format непосредственно в строковом литерале:

public String getFormattedText(String parameter) {
    return """
            Some parameter: %s
            """.formatted(parameter);
}

Все эти функции уже обеспечивают очень мощную функцию. Однако Java 14 включила некоторые дополнительные функции. Об этом мы еще поговорим.

6. Новые Escape-последовательности в Java 14

Функция второй предварительный просмотр текстовых блоков добавляет две дополнительные escape-последовательности.

6.1. Терминаторы экранирующих Линий

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

public String getIgnoredNewLines() {
    return """
            This is a long test which looks to \
            have a newline but actually does not""";
}

На самом деле этот String литерал будет просто равен обычному не прерывающемуся String :

@Test
void givenAStringWithEscapedNewLines_thenTheResultHasNoNewLines() {
    String expected = "This is a long test which looks to have a newline but actually does not";
    assertThat(subject.getIgnoredNewLines())
            .isEqualTo(expected);
}

6.2. Ускользающие пространства

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

Давайте поближе рассмотрим влияние сбежавшего пространства:

public String getEscapedSpaces() {
    return """
            line 1·······
            line 2·······\s
            """;
}

@Test
void givenAStringWithEscapesSpaces_thenTheResultHasLinesEndingWithSpaces() {
    String expected = "line 1\nline 2        \n";
    assertThat(subject.getEscapedSpaces())
            .isEqualTo(expected);
}

Примечание : пробелы в приведенном выше примере заменяются символом”·”, чтобы сделать их видимыми.

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

7. Заключение

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

Как всегда, полный исходный код статьи доступен на GitHub .