2012-12-19 6 views
22

ための方法と、私は、java.lang.Systemの次のフィールドを発見にセッター反射を用いて最終フィールド

&アウトエラーはfinalと宣言されていますが、それぞれの(public)setterメソッドを持ち、それぞれの固有のcouter-partを呼び出します。

例えば、私は正常に再直接の可能性コンソール出力をファイルに。私たちは、Javaコードでそれを初期化した後

私たちは、正確に、最終的な変数を設定することができます。

私の質問は:最終のこのルールは、ネイティブコードには適用されませんか?

+1

これらの値を設定するには、Javaは 'private static native void setOut0 )。純粋なJavaではそれはできません。 – Pshemo

+0

JNIでは、最終フィールドはスレッドセーフですか? –

答えて

12

私の質問は:最終のこのルールは、ネイティブコードには適用されませんか?

ネイティブコードでは、finalのルールを破ることができます。また、アクセスルールや基本的な型の安全性など、さまざまなことを壊す可能性があります。

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

しかし@ignisが指摘するように、System.in/out/errは「書き込み保護」(JLS 17.5.4)ではなく、通常のfinal意味を持つのであるとしてJLSで特別な言及を取得します。基本的に、これはfinal保証は、変数が変更された場合でも、ホールドを行うことを意味します。


なぜとにかくセッターがあるだろうときの変数が最終でなければなりませんか?それは1)偶発的な割り当てによって上書きされるのSystem.in/out/errを防止するため、及び2)のように変更がSecurityManagerによって制御することが可能である。この特定の場合において

+0

ただ興味があります:その理由はありますか?とにかくセッターがいるときに変数が最終的になるのはなぜですか? – moeTi

2

finalは、Javaコンパイラは何のコードは、初期化以外のフィールドを変更しようとしないことを確認します。 java.lang.Systemの違反がないのjavacの観点から

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

private static native void setOut0(PrintStream out);

異なっています。ソースコードにおける

+0

リフレクション(java.lang.reflect.Field.set(Object、Object)など)を使用して、最終フィールドの値を変更することはできませんか? –

+0

反射でさえ私たちは直接変更できませんが、最初に反射を使って最終修正を変更することができます...許可が与えられれば、aahの反射は非常に強力です –

+0

@vishal_aim Java 6以降は –

1

、それらはsetOut()方法、例えば

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

out変数を再割り当てされていない彼らは、ネイティブコードに渡されたストリームを送信し、そのコードは、現在の使用のためにそのストリームを設定する責任があります。最終的な変数は再設定されておらず、この変数はネイティブコードでは使用されません。ネイティブコードに渡されるストリームはどれでも、それを使用します。