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 package
) или просто при попытке выполнить тесты ( 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 .