【Java】「Class.getResource」と「ClassLoader.getResource」のリソース名の指定方法の違いについての解説

Javaではリソース情報(ファイルなど)を取得する処理として以下の2種類があります。

  • Class.getResource
  • ClassLoader.getResource

それぞれリソース情報を取得する処理ですが、指定するリソース名により取得結果が異なります。今回は、指定するリソース名による取得結果の違いを解説していきます。

スポンサーリンク

環境

検証に使用した実行環境を以下に記載します。

  • Windows:10
  • Java:8
    • サンプルで使用した「ClassLoader」は「sun/misc/Launcher$ExtClassLoader」になります。

サンプルとして使用したディレクトリ構成を以下に記載します。記載したディレクトリ内容を元に取得結果の解説をします。

ROOT
  └com/example/
    ├ SampleClass.java
    └ CurrentResource.txt

リソース名の指定方法パターン

リソース名の指定方法として想定しているパターンを以下に記載します。記載した内容で取得結果の違いを解説していきます。

  • 「リソース名」を指定する。
  • 「パッケージ名 + リソース名」を指定する。
  • 「/ + リソース名」を指定する。
  • 「/ + パッケージ名 + リソース名」を指定する。

リソース名に「パッケージ名」を含めて指定する場合は、パッケージ名の「.」を「/」に変換した値を指定します。例えば、パッケージ名として「com.example」を指定する場合は、「com/example」になります。

「リソース名」を指定する

リソース名のみを指定した場合のサンプルをそれぞれ以下に記載します。

Class.getResource

com.example.SampleClass.getResource("CurrentResource.txt")

この指定方法では、リソース情報を取得できます。

これは、リソース情報の検索対象を決定する内部処理で、指定したリソース名に「パッケージ名」を付与した「com/example/CurrentResource.txt」が検索対象となるためです。

Class.getClassLoader

com.example.SampleClass.getClassLoader().getResource("CurrentResource.txt")

この指定方法では、リソース情報を取得できません。

これは、リソース情報の検索対象を決定する内部処理で、指定したリソース名の「CurrentResource.txt」が検索対象となるためです。

「パッケージ名 + リソース名」を指定する

「パッケージ名 + リソース名」を指定した場合のサンプルをそれぞれ以下に記載します。

Class.getResource

com.example.SampleClass.getResource("com/example/CurrentResource.txt")

この指定方法では、リソース情報を取得できません。

これは、リソース情報の検索対象を決定する内部処理で、指定したリソース名の先頭に「パッケージ名」を付与して「com/example/com/example/CurrentResource.txt」が検索対象となるためです。

「リソース名」を指定する」と同じくリソース名の先頭にパッケージ名を付与しているため、指定したリソース名の先頭に「com/example」が付与される動作になります。

Class.getClassLoader

com.example.SampleClass.getClassLoader().getResource("com/example/CurrentResource.txt")

この指定方法では、リソース情報を取得できます。

これは、リソース情報の検索対象を決定する内部処理で、指定したリソース名の「com/example/CurrentResource.txt」が検索対象となるためです。

「/ + リソース名」を指定する

「/ + リソース名」を指定した場合のサンプルをそれぞれ以下に記載します。

Class.getResource

com.example.SampleClass.getResource("/CurrentResource.txt")

この指定方法では、リソース情報を取得できません。

これは、リソース情報の検索対象を決定する内部処理で、指定したリソース名の先頭に「/」がある場合は、先頭の「/」を削除した「CurrentResource.txt」が検索対象となるためです。

先頭に「/」を付与している場合は、先頭に「パッケージ名」を付与する動作は行われません。

Class.getClassLoader

com.example.SampleClass.getClassLoader().getResource("/CurrentResource.txt")

この指定方法では、リソース情報を取得できません。

これは、リソース情報の検索対象を決定する内部処理で、指定したリソース名の「/CurrentResource.txt」が検索対象となるためです。

「/ + パッケージ名 + リソース名」を指定する

「/ + パッケージ名 + リソース名」を指定した場合のサンプルをそれぞれ以下に記載します。

Class.getResource

com.example.SampleClass.getResource("/com/example/CurrentResource.txt")

この指定方法では、リソース情報を取得できます。

これは、リソース情報の検索対象を決定する内部処理で、指定したリソース名の先頭に「/」がある場合は、先頭の「/」を削除した「com/example/CurrentResource.txt」が検索対象となるためです。

先頭に「/」を付与している場合は、先頭に「パッケージ名」を付与する動作は行われません。

Class.getClassLoader

com.example.SampleClass.getClassLoader().getResource("/com/example/CurrentResource.txt")

この指定方法では、リソース情報を取得できません。

これは、リソース情報の検索対象を決定する内部処理で、指定したリソース名の「/com/example/CurrentResource.txt」が検索対象となるためです。

まとめ

リソース情報の取得についての動作をまとめるとそれぞれ以下のようになります。

「Class.getResource」の動作について

先頭に「/」が指定されているかどうかにより、検索対象のリソース名が変更となります。

指定方法取得先
リソース名指定したリソース名の先頭に「パッケージ名」を付与したリソース情報を取得する。
同じパッケージ内のリソース情報を取得する。
パッケージ名 + リソース名指定したリソース名の先頭に「パッケージ名」を付与したリソース情報を取得する。
パッケージ名を指定しているにも関わらず、先頭にパッケージ名が付与される。
このため、基本的にはリソース情報は取得できない。
/ + リソース名指定したリソース名の先頭の「/」を削除したリソース情報を取得する。
ルートディレクトリのリソース情報を取得する。
/ + パッケージ名 + リソース名指定したリソース名の先頭の「/」を削除したリソース情報を取得する。
「リソース名」と同じ動作となる。

「ClassLoader.getResource」の動作について

常に指定したリソース名で検索する動作になります。

指定方法取得先
リソース名指定したリソース名のリソース情報を取得する。
パッケージ名 + リソース名指定したリソース名のリソース情報を取得する。
/ + リソース名指定したリソース名のリソース情報を取得する。
/ + パッケージ名 + リソース名指定したリソース名のリソース情報を取得する。