1. 概要

このチュートリアルでは、 java.lang.Systemクラスとその機能およびコア機能について簡単に説明します。

2. IO

Systemjava.langの一部であり、その主な機能の1つは、標準のI/Oストリームへのアクセスを提供することです。

簡単に言えば、ストリームごとに1つずつ、3つのフィールドを公開します。

  • アウト
  • エラー

2.1. System.out

System.out は、標準の出力ストリームを指し、 PrintStream として公開します。これを使用して、コンソールにテキストを印刷できます。

System.out.print("some inline message");

System の高度な使用法は、 System.setOut を呼び出すことです。これを使用して、System.outが書き込む場所をカスタマイズできます。

// Redirect to a text file
System.setOut(new PrintStream("filename.txt"));

2.2. System.err

System.errSystem.outによく似ています。 両方のフィールドはPrintStream、のインスタンスであり、どちらもコンソールにメッセージを印刷するためのものです。

ただし、 System.err は標準エラーを表し、特にエラーメッセージを出力するために使用します。

System.err.print("some inline error message");

多くの場合、コンソールはエラーストリームを出力ストリームとは異なる方法でレンダリングします。

詳細については、PrintStreamのドキュメントを確認してください。

2.3. System.in

System.in はの標準を指し、 InputStream、として公開し、コンソールからの入力の読み取りに使用できます。

そして、もう少し複雑ですが、それでも管理できます。

public String readUsername(int length) throws IOException {
    byte[] name = new byte[length];
    System.in.read(name, 0, length); // by default, from the console
    return new String(name);
}

System.in.read を呼び出すと、アプリケーションは停止し、の標準からの入力を待ちます。 次の長さバイトが何であれ、ストリームから読み取られ、バイト配列に格納されます。

ユーザーが入力した他のすべてのものはストリームに残り、readへの別の呼び出しを待ちます。

もちろん、その低いレベルでの操作は困難でエラーが発生しやすい可能性があるため、BufferedReaderを使用して少しクリーンアップできます。

public String readUsername() throws IOException {
    BufferedReader reader = new BufferedReader(
      new InputStreamReader(System.in));
    return reader.readLine();
}

上記の配置では、 readLine は、ユーザーがreturnキーを押すまで、 System.in から読み取ります。これは、予想に少し近いものです。

この場合、意図的にストリームを閉じないことに注意してください。 で標準を閉じると、プログラムのライフサイクルの間、標準を再度読み取ることができなくなります!

最後に、 System.in の高度な使用法は、 System.setIn を呼び出して、別のInputStreamにリダイレクトすることです。

3. ユーティリティメソッド

システムは、次のようなことを支援するための多数のメソッドを提供します。

  • コンソールへのアクセス
  • 配列のコピー
  • 日時の観察
  • JREを終了する
  • ランタイムプロパティへのアクセス
  • 環境変数へのアクセス、および
  • ガベージコレクションの管理

3.1. コンソールへのアクセス

Java 1.6では、System.outおよびinを直接使用する以外の方法でコンソールを操作する方法が導入されました。

System.consoleを呼び出すことでアクセスできます。

public String readUsername() {
    Console console = System.console();	 	 
	 	 
    return console == null ? null :	 
      console.readLine("%s", "Enter your name: ");	 	 
}

基盤となるオペレーティングシステムと、現在のプログラムを実行するためにJavaを起動する方法によっては、 consoleがnullを返す場合があるため、を使用する前に必ず確認してください。

その他の使用法については、コンソールのドキュメントを確認してください。

3.2. 配列のコピー

System.arraycopy は、ある配列を別の配列にコピーする古いCスタイルの方法です。

ほとんどの場合、 arraycopy は、1つの完全な配列を別の配列にコピーすることを目的としています。

int[] a = {34, 22, 44, 2, 55, 3};
int[] b = new int[a.length];

System.arraycopy(a, 0, b, 0, a.length);
assertArrayEquals(a, b);

ただし、両方の配列の開始位置と、コピーする要素の数を指定できます。

たとえば、aからa[1]からbまで、b[3]から始まる2つの要素をコピーするとします。

System.arraycopy(a, 1, b, 3, 2); 
assertArrayEquals(new int[] {0, 0, 0, 22, 44, 0}, b);

また、arraycopyは次をスローすることに注意してください。

  • NullPointerExceptionいずれかの配列がnullの場合
  • IndexOutOfBoundsExceptionコピーがその範囲を超えていずれかの配列を参照している場合
  • ArrayStoreExceptionコピーの結果タイプが一致しない場合

3.3. 日時の観察

システムには時間に関連する2つの方法があります。 1つはcurrentTimeMillisで、もう1つはnanoTimeです。

currentTimeMillis は、Unixエポックから経過したミリ秒数を返します。これは1970年1月1日午前12:00UTCです。

public long nowPlusOneHour() {
    return System.currentTimeMillis() + 3600 * 1000L;
}

public String nowPrettyPrinted() {
    return new Date(System.currentTimeMillis()).toString();
}

nanoTime は、JVMの起動に関連する時間を返します。 アプリケーションで時間の経過をマークするために、これを複数回呼び出すことができます。

long startTime = System.nanoTime();
// ...
long endTime = System.nanoTime();

assertTrue(endTime - startTime < 10000);

以来注意してください nanoTime きめが細かい、 数値オーバーフローの可能性があるため、endTime

3.4. プログラムを終了する

現在実行中のプログラムをプログラムで終了したい場合は、System.exitでうまくいきます。

exit を呼び出すには、プログラムを起動したコンソールまたはシェルに送信される終了コードを指定する必要があります。

Unixの慣例により、ステータス0は通常の終了を意味し、ゼロ以外はエラーが発生したことを意味します。

if (error) {
    System.exit(1);
} else {
    System.exit(0);
}

最近のほとんどのプログラムでは、これを呼び出す必要があるのは奇妙なことに注意してください。 たとえば、Webサーバーアプリケーションで呼び出されると、サイト全体が停止する可能性があります!

3.5. ランタイムプロパティへのアクセス

System は、getPropertyを使用してランタイムプロパティへのアクセスを提供します。

そして、setPropertyclearPropertyでそれらを管理できます。

public String getJavaVMVendor() {
    System.getProperty("java.vm.vendor");
}
    
System.setProperty("abckey", "abcvaluefoo");
assertEquals("abcvaluefoo", System.getProperty("abckey"));

System.clearProperty("abckey");
assertNull(System.getProperty("abckey"));

-D で指定されたプロパティには、getPropertyからアクセスできます。

デフォルトを提供することもできます。

System.clearProperty("dbHost");
String myKey = System.getProperty("dbHost", "db.host.com");
assertEquals("db.host.com", myKey);

また、 System.getProperties は、すべてのシステムプロパティのコレクションを提供します。

Properties properties = System.getProperties();

そこからプロパティ操作を実行できます。

public void clearAllProperties() {
    System.getProperties().clear();
}

3.6. 環境変数へのアクセス

System は、getenvを使用した環境変数への読み取り専用アクセスも提供します。

たとえば、 PATH 環境変数にアクセスする場合は、次のようにします。

public String getPath() {
    return System.getenv("PATH");
}

3.7. ガベージコレクションの管理

通常、ガベージコレクションの取り組みは私たちのプログラムには不透明です。 ただし、場合によっては、JVMに直接提案したいことがあります。

System.runFinalization は、JVMがファイナライズルーチンを実行することを提案できるメソッドです。

System.gc は、JVMがガベージコレクションルーチンを実行することを提案できるメソッドです。

これら2つの方法のコントラクトは、ファイナライズまたはガベージコレクションの実行を保証しないため、それらの有用性は狭いです。

ただし、デスクトップアプリが最小化されたときに gc を呼び出すなど、最適化として実行することもできます。

public void windowStateChanged(WindowEvent event) {
    if ( event == WindowEvent.WINDOW_DEACTIVATED ) {
        System.gc(); // if it ends up running, great!
    }
}

ファイナライズの詳細については、ファイナライズガイドをご覧ください。

4. 結論

この記事では、Systemが提供するいくつかのフィールドとメソッドを確認しました。 完全なリストは、公式システムドキュメントにあります。

また、Githubでこの記事のすべての例を確認してください。