2012-12-19 3 views
22

utilisant la réflexion et aussi de la src.zip disponible dans l'installation JDK par l'installateur par http://docs.oracle.com véhiculée, je trouve les champs suivants de java.lang.System,méthodes setter pour les champs finaux

à, sur & err sont déclarés comme définitifs, mais ils ont des méthodes setter (publiques) respectives qui invoquent à leur tour leur partie couter native respective.

Par exemple, je pourrais rediriger avec succès la sortie de la console vers un fichier.

Nous pouvons définir les variables finales exactement une fois que nous l'avons initialisé dans le code Java.

Ma question est la suivante: cette règle de la finale ne s'applique-t-elle pas au code natif?

+1

Pour définir ces valeurs, Java utilise des méthodes natives telles que private private native void setOut0 (PrintStream out) '. En pur Java, vous ne pouvez pas le faire. – Pshemo

+0

Donc, avec JNI, les champs finaux sont thread-safe? –

Répondre

12

Ma question est la suivante: cette règle de final ne s'applique-t-elle pas au code natif?

Le code natif peut enfreindre les règles sur final. Il peut également casser les règles d'accès et la sécurité de base du type, et diverses autres choses.

Le point sur final champs qui ne sont pas réellement immuables est reconnu dans le JLS: voir JLS 17.5.3. L'essentiel de ceci est que si vous changez un final (via la réflexion par exemple), certaines garanties ne tiennent plus. Et changer la valeur d'un final qui représente une constante de temps de compilation est susceptible de n'avoir aucun effet du tout.

Mais comme @ignis souligne, System.in/out/err obtenir une mention spéciale dans le JLS comme étant « protégé en écriture » (JLS 17.5.4) plutôt que d'avoir les final normales sémantique. Fondamentalement, cela signifie que le final garantit maintenir même si les variables sont modifiées.


Pourquoi les variables définitives quand il y aura un poseur de toute façon?

Dans ce cas particulier, il est égal à 1) pour empêcher System.in/out/err d'être mis à mal par une cession accidentelle, et 2) de sorte que des changements peuvent être contrôlés par le SecurityManager.

+0

juste par intérêt: y a-t-il une raison à cela? pourquoi les variables sont-elles définitives quand il y aura un setter de toute façon? – moeTi

2

final permet à Java Compiler de s'assurer qu'aucun code ne tente de modifier le champ sauf l'initialisation. En java.lang.System il est différent

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

private static native void setOut0(PrintStream out);

Du point de vue de javac il n'y a pas violation.

+0

en utilisant la réflexion (comme java.lang.reflect.Field.set (Object, Object) etc.) nous ne pouvons pas non plus modifier la valeur d'un champ final? –

+0

même avec la réflexion que nous ne pouvons pas modifier directement, mais nous pouvons en modifiant ce modificateur final en utilisant la réflexion ... aah réflexion est si puissante si les permissions sont accordées –

+0

@vishal_aim Testez maintenant, puisque Java 6 vous ne pouvez pas utiliser –

1

dans le code source, ils ne sont pas réaffectant par exemple out variable dans la méthode setOut()

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

ils envoient le flux transmis en code natif, et que le code est responsable de définir ce flux pour une utilisation courante. La variable finale n'est pas réinitialisée et cette variable n'est pas utilisée en code natif, quel que soit le flux qu'elle passe au code natif.

Questions connexes