2009-05-11 19 views

Antwort

55

Ich würde vermuten, dass es auf den Typ und den Compiler abhängt (auf den zweiten Gedanken hatte es sicher besser nicht!). Der Compiler von Sun inliniert primitive Konstanten, aber ich weiß nicht, ob sie den Eintrag vollständig aus der Klasse entfernen. Ich werde herausfinden.

Bearbeiten: Ja, Sie können immer noch auf sie zugreifen, auch wenn sie inline sind. Testklasse:

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)); 
     } 
    } 
} 

Ausgang:

 
CONST_INT: 100 
CONST_STRING: String 
CONST_OBJECT: xyz 

javap -c Ausgang:

 
Compiled from "ReflectionConstantTest.java" 
public class scratch.ReflectionConstantTest extends java.lang.Object{ 
public scratch.ReflectionConstantTest(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."":()V 
    4: return 

public static void main(java.lang.String[]) throws java.lang.Exception; 
    Code: 
    0: bipush 100 
    2: istore_1 
    3: ldc  #2; //String String 
    5: astore_2 
    6: getstatic  #3; //Field CONST_OBJECT:Ljava/lang/Object; 
    9: astore_3 
    10: ldc_w #4; //class scratch/ReflectionConstantTest 
    13: invokevirtual #5; //Method java/lang/Class.getDeclaredFields:()[Ljava/lang/reflect/Field; 
    16: astore 4 
    18: aload 4 
    20: arraylength 
    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: astore 7 
    40: aload 7 
    42: iconst_1 
    43: invokevirtual #6; //Method java/lang/reflect/Field.setAccessible:(Z)V 
    46: getstatic  #7; //Field java/lang/System.out:Ljava/io/PrintStream; 
    49: new  #8; //class java/lang/StringBuilder 
    52: dup 
    53: invokespecial #9; //Method java/lang/StringBuilder."":()V 
    56: aload 7 
    58: invokevirtual #10; //Method java/lang/reflect/Field.getName:()Ljava/lang/String; 
    61: invokevirtual #11; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    64: ldc  #12; //String : 
    66: invokevirtual #11; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    69: aload 7 
    71: aconst_null 
    72: invokevirtual #13; //Method java/lang/reflect/Field.get:(Ljava/lang/Object;)Ljava/lang/Object; 
    75: invokevirtual #14; //Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 
    78: invokevirtual #15; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
    81: invokevirtual #16; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    84: iinc 6, 1 
    87: goto 26 
    90: return 

static {}; 
    Code: 
    0: new  #8; //class java/lang/StringBuilder 
    3: dup 
    4: ldc  #17; //String xyz 
    6: invokespecial #18; //Method java/lang/StringBuilder."":(Ljava/lang/String;)V 
    9: putstatic  #3; //Field CONST_OBJECT:Ljava/lang/Object; 
    12: return 

} 

Sie können sehen, dass CONST_INT ist inlined, aber CONST_STRING und CONST_OBJECT (natürlich) nicht. Dennoch ist CONST_INT noch reflektiv verfügbar.

+0

Dies löste mein Problem, danke! Ich bin neugierig, warum wir f.setAccessible aufrufen müssen (true). Was ist der Grund dafür, dass statische Modifikatoren überhaupt nicht zugänglich sind? – gsingh2011

+0

@ gsingh2011: Der einzige Grund, der notwendig ist, ist zu demonstrieren, dass sogar auf private Konstanten durch Reflektion zugegriffen werden kann (Sie können beobachten, dass die drei Konstanten in dem Beispiel als privat deklariert sind). Öffentliche Konstanten müssten nicht zugänglich gemacht werden, da sie bereits zugänglich sind. –

+0

Ahh, ich verstehe. Ich habe gerade festgestellt, dass mein Problem aufgetreten ist, weil ich meinem Feld keinen öffentlichen/privaten Modifikator bereitgestellt habe und meinen Code dann in Pakete umstrukturiert habe. Danke trotzdem für die Antwort. – gsingh2011

1

Wenn Open Source-Bibliotheken auf Ihrem Projekt erlaubt Ihnen

FieldUtils.readDeclaredStaticField

public class Test { 
    public final static String CONSTANT="myConstantValue"; 
} 

In einer anderen Klasse verwenden können, können Sie Verwenden Sie:

Object value = FieldUtils.readDeclaredStaticField(Test.class, "CONSTANT"); 
System.out.println(value); 

Sie sehen "MyConstantValue" in der Konsole.

0

Um nur den Namen und Wert zu erhalten, ist setAccessible (true) nicht erforderlich. Hier ist ein nützliches Beispiel, wenn Sie sich mit Konstanten beschäftigen müssen, die in einer Schnittstelle deklariert sind, und die symbolischen Namen haben wollen:

Verwandte Themen