1

クラスの実装java.lang.Systemを調べると、次のことがわかります。

public final static PrintStream out = null;

その定義だけから、 の値System.outは常に であることがわかりますnull。ただし、プログラムの開始時に初期化され ( System.initializeSystemClass()JVM によってメソッドが自動的に呼び出されます)、セキュリティ チェックを実行する を使用してその値を変更できます。次に、値を変更するメソッドであるメソッドにSystem.setOut呼び出しを委任します。の。宣言されているのに値を変更できるのはなぜですか?setOut0nativeSystem.outSystem.outfinal

4

2 に答える 2

6

これは、API の歴史的な疣贅です。JLS は実際には特殊なケースSystem.{in,out,err}であり、API が現在設計されている場合は、おそらく別の宣言があるでしょう。

この奇妙な動作は、Java の の定義を無視することによって実際に実装されていますSystem。は、JVM の外部の環境に対する Java プログラムのインターフェースである ( 、、 system 、およびその他のいくつかのSystemクラスとともに) コア クラスの 1 つです。それらのタスクを実行するには、JRE によって (ほとんどの場合) ネイティブ コードで提供される必要があります。この場合、実際の C コードは、Java API が field を宣言するという事実を単に無視します。RuntimeObjectClassLoaderSystemfinal

于 2013-08-14T21:54:55.387 に答える
1

final フィールドの値をネイティブ コードで変更する方法を尋ねています。

これは、ネイティブ コードの他のビットがフィールド値を変更するのと同じように機能します。変数の変更はfinal、コンパイラによってコンパイル時に検出されます。への呼び出しによって開始される明示的なチェックを除いて、ランタイム チェックはありませんField.set()。実行時のメモリ保護やその他の関係はありません。たとえそうであったとしても、オペレーティング システムではなく JVM によって行われます。ネイティブ コードは、フィールドのメタ データを気にする必要はありません。メモリにバイトを設定するだけで済みます。これは、Java コンパイラのコンパイル時チェックの範囲外です。

コンパイラがフィールドに対して実行できる最適化のため、フィールドに対するネイティブ コードの変更は、プログラム全体では表示finalされない場合さえあります。それが、Java 7より前のことでした。finalnullPrintStream()

于 2013-08-15T00:47:11.033 に答える