«1. Обзор

Когда мы пытаемся использовать переменную, которая слишком длинна для компилятора Java (больше 64 КБ), мы получаем от компилятора ошибку «Слишком длинная строка константы».

В этом уроке мы покажем, как решить эту ошибку.

2. Описание проблемы

Давайте воспроизведем проблему, написав небольшой тест, в котором мы объявили слишком длинную строку:

@Test
public void whenDeclaringTooLongString_thenCompilationError() {
    String stringTooLong = "stringstringstring ... 100,000 characters ... string";  
    assertThat(stringTooLong).isNotEmpty();
}

Строка, содержащаяся в нашей переменной stringTooLong, содержит текст с более чем 100 000 символы. Строка с этими характеристиками доступна в файле, доступном по ссылке GitHub в конце. Чтобы вызвать ошибку, скопируйте ее содержимое и замените значение stringTooLong.

Обратите внимание, если мы запустим этот тест из некоторых IDE, мы не получим никаких ошибок.

Причина в том, что IDE обычно более снисходительны. Однако при попытке скомпилировать проект (пакет mvn) или просто при попытке выполнить тесты (mvn test) из командной строки мы получим следующий вывод:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.058 s
[INFO] Finished at: 2020-03-14T17:56:34+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:testCompile (default-testCompile) on project core-java-strings: Compilation failure
[ERROR] <path to the test class>:[10,32] constant string too long

Это связано с тем, что длина строковой константы в файл класса ограничен 2 ^ 16 байтами в кодировке UTF-8.

3. Решение проблемы

Как только мы воспроизведем проблему, давайте найдем способ ее решить. Лучше всего хранить нашу строку в отдельном файле, а не в объявленной переменной или константе.

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

@Test
public void whenStoringInFileTooLongString_thenNoCompilationError() throws IOException {
    FileInputStream fis = new FileInputStream("src/test/resources/stringtoolong.txt");
    String stringTooLong = IOUtils.toString(fis, "UTF-8");
    assertThat(stringTooLong).isNotEmpty();
}

Другой способ решить эту проблему — сохранить содержимое нашей переменной в свойствах файл, а затем получить к нему доступ из нашего тестового метода:

@Test
public void whenStoringInPropertiesString_thenNoCompilationError() throws IOException {
    try (InputStream input = new FileInputStream("src/main/resources/config.properties")) {         
        Properties prop = new Properties();
        prop.load(input);
        String sValue = prop.getProperty("stringtoolong");
        assertThat(sValue).isNotEmpty();
    }  
}

Теперь, если мы попытаемся скомпилировать наш проект или выполнить тесты, все будет работать:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.433 s
[INFO] Finished at: 2020-03-14T18:23:54+01:00
[INFO] ------------------------------------------------------------------------

Конечно, мы могли бы также ввести конкатенацию с нашей строкой , но это не рекомендуется. Если у нас есть такая длинная строка, наши файлы Java, вероятно, в любом случае не лучший дом для нее.

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

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

Как всегда, вы можете найти код на GitHub.