La valeur d'une variable de classe finale statique Java peut-elle être extraite par réflexion?
Je suppose que cela dépend du type et du compilateur (à la réflexion, il valait mieux ne pas!). Les constantes primitives en ligne du compilateur de Sun, mais je ne sais pas si elles suppriment entièrement l'entrée de la classe. Je trouverai.
Edit: Oui, vous pouvez toujours y accéder même s’ils sont en ligne. Classe de test:
public class ReflectionConstantTest {
private static final int CONST_INT = 100;
private static final String CONST_STRING = "String";
private static final Object CONST_OBJECT = new StringBuilder("xyz");
public static void main(String[] args) throws Exception {
int testInt = CONST_INT;
String testString = CONST_STRING;
Object testObj = CONST_OBJECT;
for (Field f : ReflectionConstantTest.class.getDeclaredFields()) {
f.setAccessible(true);
System.out.println(f.getName() + ": " + f.get(null));
}
}
}
Sortie:
CONST_INT: 100 CONST_STRING: Chaîne CONST_OBJECT: xyz
javap -c
sortie:
Compilé à partir de "ReflectionConstantTest.Java" La classe publique scratch.ReflectionConstantTest étend Java.lang.Object { Public scratch.ReflectionConstantTest (); Code: 0: aload_0 1: invokespecial # 1; // Méthode Java/lang/Object. "" :() V 4: return Public static void main (Java.lang.String []) lève Java.lang.Exception; Code: 0: bipush 100 2: istore_1 3: ldc # 2; // String String 5: astore_2 6: getstatic # 3; // Champ CONST_OBJECT: Ljava/lang/Object; 9: astore_3 10: ldc_w # 4; // classe scratch/ReflectionConstantTest 13: invokevirtual # 5; // Méthode Java/lang/Class.getDeclaredFields: () [Ljava/lang/reflect/Field; 16: au magasin 4 18: plus de 4 20: longueur de l'arme 21: istore 5 23: iconst_0 24: istore 6 26: iload 6 28: iload 5 30: if_icmpge 90 33: aload 4 35: iload 6 37: aaload 38: au magasin 7 40: environ 7 42: iconst_1 43: invokevirtual # 6; // Méthode Java/lang/reflect/Field.setAccessible: (Z) V 46: getstatic # 7; // Champ Java/lang/System.out: Ljava/io/PrintStream; 49: nouveau n ° 8; // classe Java/lang/StringBuilder 52: dup 53: invokespecial # 9; // Méthode Java/lang/StringBuilder. "" :() V 56: plus de 7 58: invokevirtual # 10; // Méthode Java/lang/reflect/Field.getName :() Ljava/lang/String; 61: invokevirtual # 11; // Méthode Java/lang/StringBuilder.append: (Ljava/lang/String;) Ljava/lang/StringBuilder; 64: ldc # 12; //Chaîne : 66: invokevirtual # 11; // Méthode Java/lang/StringBuilder.append: (Ljava/lang/String;) Ljava/lang/StringBuilder; 69: environ 7 71: aconst_null 72: invokevirtual # 13; // Méthode Java/lang/reflect/Field.get: (Ljava/lang/Object;) Ljava/lang/Object; 75: invokevirtual # 14; // Méthode Java/lang/StringBuilder.append: (Ljava/lang/Object;) Ljava/lang/StringBuilder; 78: invokevirtual # 15; // Méthode Java/lang/StringBuilder.toString :() Ljava/lang/String; 81: invokevirtual # 16; // Méthode Java/io/PrintStream.println: (Ljava/lang/String;) V 84: Iinc 6, 1 87: passez à 26 90: retour Static {}; Code: 0: nouveau # 8; // classe Java/lang/StringBuilder 3: dup 4: ldc # 17; // String xyz 6: invokespecial # 18; // Méthode Java/lang/StringBuilder. "" :( Ljava/lang/String;) V 9: putstatic # 3; // Champ CONST_OBJECT: Ljava/lang/Object; 12: retour }
Vous pouvez voir que CONST_INT
est en ligne, mais CONST_STRING
et CONST_OBJECT
(bien sûr) ne le sont pas. Pourtant, CONST_INT
est toujours disponible de manière réfléchie.
Oui. (Seulement, il n’existe pas de statique, instance. C’est statique, non-instance.)
> Si le champ sous-jacent est un champ statique, l'argument obj est ignoré. il peut être nul.
(inclure un avertissement standard indiquant que la plupart des utilisations de la réflexion sont une mauvaise idée)
Si les bibliothèques open-source sont autorisées sur votre projet, vous pouvez utiliser
FieldUtils.readDeclaredStaticField
public class Test {
public final static String CONSTANT="myConstantValue";
}
Dans une autre classe, vous pouvez utiliser:
Object value = FieldUtils.readDeclaredStaticField(Test.class, "CONSTANT");
System.out.println(value);
Vous verrez "myConstantValue" dans la console.
Obtenir le nom et la valeur ne nécessite pas setAccessible (true). Voici un exemple utile lorsque vous devez gérer des constantes déclarées dans une interface et que vous voulez les noms symboliques:
interface Code {
public static final int FOO = 0;
public static final int BAR = 1;
}
...
try {
for (Field field : Code.class.getDeclaredFields()) {
String name = field.getName();
int value = field.getInt(null);
System.out.println(name + "=" + value);
}
}
catch (IllegalAccessException e) {
System.out.println(e);
}