環境
この記事は以下の環境で、稼働確認を実施しました。
C:\>java -version
openjdk version "11.0.3" 2019-04-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.3+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.3+7, mixed mode)
事象
以下のMain.java
はクラスパス上に存在するqueen.properties
を読み込んだのち、その内容を整形して表示するものです。
import java.io.IOException;
import java.util.Properties;
public class Main {
public static void main(String[] args) {
try (var in = Main.class.getClassLoader().getResourceAsStream("queen.properties")) {
var properties = new Properties();
properties.load(in);
for (var key : properties.stringPropertyNames()) {
var value = properties.getProperty(key);
var message = String.format("key=`%s` value=`%s`", key, value);
System.out.println(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
なおqueen.properties
の内容は次の通りです。
queen.vocal = Freddie Mercury
queen.guitar = Brian May
queen.bass = John Deacon
queen.drum = Roger Taylor
さてMain.java
をjavac
によりコンパイルして、Main.class
を生成し、以下の通り実行したところ、エラーが発生し、想定通りの挙動を見せませんでした。
C:\>java -cp properties\queen.properties; Main
Exception in thread "main" java.lang.NullPointerException: inStream parameter is null
at java.base/java.util.Objects.requireNonNull(Objects.java:246)
at java.base/java.util.Properties.load(Properties.java:403)
at Main.main(Main.java:8)
このケースではproperties
ディレクトリに格納されたqueen.properties
をクラスパスに追加したいという意図がありました。そのため、クラスパスを指定する-cp
オプションにproperties\queen.properties
を指定したのですが、うまく動作しなかったようです。
原因と対策
ワイルドカード(*
)を利用する場合などを別にすると、クラスパスへの指定方法はおおよそ次のようなルールになっているようです。
- jarファイルやzipファイルはファイル名を指定する。
- それ以外はディレクトリ名を指定する。
propertiesファイルをクラスパスに指定したいというのが今回の要望でした。したがって、クラスパスの指定方法としては後者が正解です。そこで、-cp
オプションにファイル名ではなく、ディレクトリ名を指定したところ、想定通りの挙動になりました。
C:\>java -cp properties; Main
key=`queen.guitar` value=`Brian May`
key=`queen.drum` value=`Roger Taylor`
key=`queen.vocal` value=`Freddie Mercury`
key=`queen.bass` value=`John Deacon`