25

リフレクションを使用し、 http://docs.oracle.comが提供するインストーラーによってインストールされた JDK で利用可能な src.zip から、次のフィールドを見つけましたjava.lang.System

inouterrは final として宣言されていますが、それぞれの (パブリック) セッター メソッドがあり、それぞれのネイティブ カウンター部分を呼び出します。

たとえば、コンソール出力をファイルに正常にリダイレクトできました。

Java コードで初期化したら、最終変数を正確に設定できます。

私の質問は次のとおりです:この最終規則はネイティブコードには適用されませんか?

4

3 に答える 3

15

私の質問は次のとおりです:この最終規則はネイティブコードには適用されませんか?

ネイティブ コードは のルールに違反する可能性がありますfinal。また、アクセス ルールと基本的な型の安全性、およびその他のさまざまなことを破ることができます。

finalフィールドが実際には不変ではないという点は、実際には JLS で認識されています。 JLS 17.5.3を参照してください。これの要点は、final(たとえばリフレクションを介して) a を変更すると、特定の保証が保持されなくなるということです。また、コンパイル時定数を表す a の値を変更しfinalても、まったく影響がない可能性があります。

しかし、@ignis が指摘しているように、JLS では、通常のセマンティクスではなく、System.in/out/err「書き込み保護」( JLS 17.5.4 ) として特別な言及があります。final基本的に、これは変数が変更されてもfinal保証が保持されることを意味します。


とにかくセッターがあるのに、なぜ変数を最終にする必要があるのですか?

この特定のケースでは、1)System.in/out/err偶発的な割り当てによって上書きされないようにするため、および 2) によって変更を制御できるようにするためSecurityManagerです。

于 2012-12-19T10:53:40.147 に答える
2

final初期化以外のコードがフィールドを変更しようとしないことを Java コンパイラーに保証させます。java.lang.System では異なります

public static void setOut(PrintStream out) { checkIO(); setOut0(out); }

private static native void setOut0(PrintStream out);

javac の観点からは、違反はありません。

于 2012-12-19T10:58:08.167 に答える
1

ソースコードでは、メソッドoutの変数などを再割り当てしていませんsetOut()

public static void setOut(PrintStream out) {
 checkIO();
 setOut0(out);
}

渡されたストリームをネイティブ コードに送信し、そのコードはそのストリームを現在使用するように設定する責任があります。したがって、最終変数は再設定されておらず、この変数はネイティブ コードでは使用されません。ネイティブ コードに渡すストリームが何であれ、それを使用します。

于 2012-12-19T10:59:16.340 に答える