1. 概要

Javaコンパイラには長すぎる(64 KBを超える)変数を使用しようとすると、次のようになります。 コンパイラからの「定数文字列が長すぎます」エラー。

このチュートリアルでは、そのエラーを解決する方法を示します。

2. 問題の説明

長すぎるStringを宣言した小さなテストを記述して、問題を再現してみましょう。

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

stringTooLong変数に含まれるStringには、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

これは、クラスファイルの文字列定数の長さがUTF-8エンコーディングで2^16バイトに制限されているためです。

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にあります。