Javaのシステムプロパティって何？

今日の議題は「システムプロパティ」です。これも本では簡単にしか載ってなかったので、公式ドキュメントなどを確認しながらまとめていくことがここの目標。


# システムプロパティとは
まず、プロパティとは何か。
プロパティとは、日本語で「**属性**」だったり「**特性**」と訳します。つまり、ある対象物の特徴に関する情報を表しています。
例えば、あるファイルのプロパティを覗くと、いつ作られたか、拡張しは何か、エンコードは何か、など様々なプロパティを含んでいます。

ではシステムプロパティとは、なんでしょうか。
これは、Javaのシステム、つまりJVMに関する情報のことを示しています。
Javaで扱う際の形式は、Map<String, String>で扱え、Propertiesクラスに格納されています。Propertiesクラスについては後ほど見るとして、Map<String, String>とは、文字列と文字列のペアを複数格納できる入れ物でした。
より具体的な例としては、例えば、
Javaのバージョン：11.0.9
というように文字列を文字列がペアになってPropertiesクラスに格納されています。
他にも以下のように様々なものが含まれています。全て覚えている必要はないが、ものすごく便利なので何が何を表しているかくらいは理解したいところ。

| キー| 対応する値の説明 | 
|:-----------|:------------|
| java.version|	Java Runtime Environmentのバージョン
java.vendor	|Java Runtime Environmentのベンダー
java.vendor.url	|JavaベンダーのURL
java.home	|Javaのインストール先ディレクトリ
java.vm.specification.version|	Java仮想マシンの仕様バージョン
java.vm.specification.vendor|	Java仮想マシンの仕様のベンダー
java.vm.specification.name|	Java仮想マシンの仕様名
java.vm.version	|Java仮想マシンの実装バージョン
java.vm.vendor	|Java仮想マシンの実装のベンダー
java.vm.name	|Java仮想マシンの実装名
java.specification.version|	Java Runtime Environmentの仕様バージョン
java.specification.vendor|	Java Runtime Environmentの仕様のベンダー
java.specification.name	|Java Runtime Environmentの仕様名
java.class.version	|Javaクラスの形式のバージョン番号
java.class.path	|Javaクラス・パス
java.library.path|	ライブラリのロード時に検索するパスのリスト
java.io.tmpdir	|デフォルト一時ファイルのパス
java.compiler	|使用するJITコンパイラの名前
java.ext.dirs	|拡張ディレクトリDeprecated.のパスこのプロパティおよびこれを実装するメカニズムは将来のリリースで削除されます。
os.name	|オペレーティング・システム名
os.arch	|オペレーティング・システムのアーキテクチャ
os.version	|オペレーティング・システムのバージョン
file.separator	|ファイル区切り文字(UNIXでは"/")
path.separator	|パス区切り文字(UNIXでは":")
line.separator	|行区切り文字(UNIXでは"\n")
user.name	|ユーザーのアカウント名
user.home	|ユーザーのホーム・ディレクトリ
user.dir	|ユーザーの現在の作業ディレクトリ


# Propertiesクラス
[Propertiesクラスの公式ドキュメント](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Properties.html)

公式ドキュメントによると
Propertiesクラスは
> プロパティのセットを表す。

これは、上で議論したことを行っています。このクラスは様々なメソッドを持っていますが、そもそもこのPropertiesクラスはシステムクラスのgetProperties()メソッドによって呼び出される。
[Systemクラスの公式ドキュメント](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/System.html)

また、Map形式なので、keyを使ってvalueを呼び出せます。それはSystemクラスのgetProperty(key)メソッドを使って
対応するvalueを呼び出すことができる。

システムプロパティを上手く使えば、環境依存を排除できます。例えば、

```java
System.out.println("私の名前は\n太郎です。");
```
というコードはOSごとに違う表示をしてしまう。
Linuxであれば、
> 私の名前は
太郎です。

であるが、古いMac OSでは、
> 私の名前は太郎です。

となります。これはOSによって"\n"の意味合いが異なってしまうからである。
上のコードをどのOSでも改行を含むためには下記を採用すれば良い。

```java
final String BR = System.getProperty("line.separator");
System.out.println("私の名前は" + BR + "太郎です。");
```

上記であれば、OSに沿った改行を表す特殊文字が入るため、必ず改行されることになる。
上記の例のように、上手く使えばOSに依存しないプログラムが書くことができる。

今までは、プロパティをゲットしてくる関数を見てきたが、セットする関数も存在する。その関数はSYstem.setProperty(key, value)メソッドである。

ここで注意しておくことがある。
システムプロパティはどのようなクラスからも直接読み書きできる便利な格納領域であるが、**不具合の原因になりやすいために濫用は禁物**である。

# システムプロパティの取得のコード例

```java
	public static void main(String[] args) {
		// Propertiesクラスを取得
		Properties properties = System.getProperties();

		Iterator<String> iterator = properties.stringPropertyNames().iterator();

		System.out.println("「システムプロパティ一覧」");
		while (iterator.hasNext()) {
			String key = iterator.next();
			System.out.print(key + " = ");
　　　　　　　// getProperty(key)で指定されたシステムプロパティの値を返す。
			System.out.println(System.getProperty(key));
		}

		final String LINEBREAKER = System.getProperty("line.separator");
		System.out.println("全てのOSで改行" + LINEBREAKER + "されるよ。" );
	}
```


今日はこの辺で。システムプロパティをコードでまだ使ったことないので実感が湧きませんが、常にJVMの情報を得られるクラスを知れたことは嬉しき。

# 参照
- https://docs.oracle.com/javase/jp/8/docs/api/java/util/Properties.html
- https://docs.oracle.com/javase/jp/8/docs/api/java/util/Map.html