2009-05-11 39 views

Trả lời

55

Tôi đoán rằng nó phụ thuộc vào loại và trình biên dịch (trên suy nghĩ thứ hai, nó có chắc chắn tốt hơn không!). Trình biên dịch của Sun inline hằng số nguyên thủy, nhưng tôi không biết nếu họ loại bỏ hoàn toàn mục nhập từ lớp. Tôi sẽ tìm ra.

Chỉnh sửa: Có, bạn vẫn có thể truy cập ngay cả khi chúng được inlined. class 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)); 
     } 
    } 
} 

Output:

 
CONST_INT: 100 
CONST_STRING: String 
CONST_OBJECT: xyz 

javap -c đầu ra:

 
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 

} 

Bạn có thể thấy rằng CONST_INT được sắp xếp theo hàng nhưng CONST_STRINGCONST_OBJECT (tất nhiên) thì không. Tuy nhiên, CONST_INT vẫn có sẵn một cách phản ánh.

+0

Điều này giải quyết được vấn đề của tôi! Tôi tò mò là tại sao chúng ta phải gọi f.setAccessible (true). Điểm của việc sửa đổi tĩnh không thể truy cập ở địa điểm đầu tiên là gì? – gsingh2011

+0

@ gsingh2011: Lý do duy nhất cần thiết là chứng minh rằng thậm chí các hằng số riêng tư có thể được truy cập thông qua sự phản chiếu (bạn có thể quan sát thấy ba hằng số trong ví dụ được khai báo riêng). Các hằng số công khai sẽ không cần phải đặt có thể truy cập được vì chúng đã có thể truy cập được. –

+0

Ahh, tôi hiểu rồi. Tôi chỉ nhận ra vấn đề của tôi xảy ra bởi vì tôi đã không cung cấp một công cụ sửa đổi công/tư nhân cho lĩnh vực của tôi, và sau đó refactored mã của tôi thành các gói. Cảm ơn anyway cho phản ứng. – gsingh2011

1

Nếu open- thư viện nguồn được phép vào dự án của bạn, bạn có thể sử dụng

FieldUtils.readDeclaredStaticField

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

Trong lớp khác, bạn có thể sử dụng:

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

Bạn sẽ thấy "myConstantValue" trong giao diện điều khiển.

0

Chỉ nhận tên và giá trị không yêu cầu setAccessible (true). Dưới đây là ví dụ hữu ích khi bạn phải xử lý các hằng số được khai báo trong giao diện và muốn tên biểu tượng:

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); 
} 
Các vấn đề liên quan