2011-11-14 53 views
0

我有以下类:静态块和Field.get(空)与静态不原始数据字段

public class A { 

    static { 
     B.load(A.class); 
    } 

    public static final C field1 = new C("key1", "value1"); 

    public static final C field2 = new C("key2", "value2"); 

    public static void main(String[] args) { 
     System.out.println(A.field1); 
    } 

} 

public class B { 

    public static void load(Class<?> clazz) { 
     for (Field field : clazz.getFields()) { 
      try { 
       System.out.println("B.load -> field is " + field.get(null)); 
      } catch (IllegalArgumentException e) { 
       e.printStackTrace(); 
      } catch (IllegalAccessException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

public class C { 

    private final String key; 

    private final String value; 

    public C(String key, String value) { 
     super(); 
     this.key = key; 
     this.value = value; 
    } 

    public String getKey() { 
     return this.key; 
    } 

    public String getValue() { 
     return this.value; 
    } 

    @Override 
    public String toString() { 
     return "C [key=" + this.key + ", value=" + this.value + "]"; 
    } 

} 

当A是执行我得到:

B.load -> field is null 
B.load -> field is null 
C [key=key1, value=value1] 

被执行时,它为什么field.get(空)返回null值?我也没有例外,Javadoc似乎没有解释这种行为。

回答

1

我相信所有的静态成员(静态块)被执行,声明的顺序初始化(静态字段)。尝试将类A的静态块放置在类的最后,或者至少放在静态字段之后。勒米知道这是否有所作为。

编辑:关于对原语和字符串的行为信息...

当你有一个最终的静态字段是一个原始的或文字字符串(或可静态评估中的一个结果的表达式这些),它被认为是编译时常量。基本上,设置这样一个值并不需要“计算”,比如调用构造函数或评估其他可能尚未初始化的字段。虽然字符串不是原语,但是它们在编译时会给予特殊的处理以使代码中的字符串文字成为可能。

这意味着这样的字段可以作为一类已经装载尽可能快分配,并准备好初始化。虽然我不知道关于这方面的规格细节,但试验反思表明这是必然发生的事情。 Java语言规范的

之后的,是与理解这种行为:

+0

谢谢,它解决了这个问题,但还是有一些我不明白。为什么如果我使用原始数据类型而不是C出现问题(例如,静态int field1 = 1和静态int field2 = 2与静态块包含B.load之前声明的领域)? – Laurent

+0

@Laurent我会编辑一些信息。 –

1

在您的A类中,您必须声明之前的静态函数对您的静态函数的调用。

public static final C field1 = new C("key1", "value1"); 

public static final C field2 = new C("key2", "value2"); 

static { 
    B.load(A.class); 
} 

Java tutorial解释它:

A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.