2012-06-19 80 views
11
class Test { 
    public static void main(String[] args) throws Exception { 
     Test t = new Test(); 
     System.out.println(t.field); 
     System.out.println(t.getClass().getField("field").get(t)); 

     int[] ar = new int[23]; 
     System.out.println(ar.length); 
     System.out.println(ar.getClass().getField("length").get(ar)); 

    } 
    public int field = 10; 
}; 

获取Java数组在字段“长度”当我运行上面的代码,我得到的命令行下面的结果 -使用反射

10 
10 
23 
Exception in thread "main" java.lang.NoSuchFieldException: length 
    at java.lang.Class.getField(Class.java:1520) 
    at Test.main(Test.java:9) 

为什么我无法访问数组中的字段“长度”?

回答

3

我认为这可能是JVM实现中的一个错误。这里是我的推理:

  1. the documentation for Class.getFieldgetField应作为部分(1)它的搜索算法,发现length如果它被声明为public字段:“如果是C声明了一个公共字段名称明确指出,那就是要反映的领域。“

  2. 根据the Java Language Specification,每个数组都有length声明为“公共最终字段长度,其中包含数组的组成部分数量”。

  3. 由于此字段声明为名称lengthgetField要么抛出SecurityException的记载,还是应该返回Field对象。

现在有趣的是,Class.getFields方法明确地提到,“对于数组类隐式长度字段不是由该方法反映出来。用户代码应该使用类阵列的方法来操作阵列。”这似乎不是平行的getField,所以这可能是我的错误阅读或只是不好的文档。

希望这会有所帮助!

+0

它也可能是JLS中的一个bug;)但它绝对是奇怪的。 – brimborium

8

有一个特殊的java.lang.reflect.Array类。 length是不正常的领域。要访问它,有一个特殊的方法getLength

+0

虽然这确实允许反射正常工作,但我认为这不能回答这个问题。至少在我阅读时,OP的问题就是上述代码失败的原因。 – templatetypedef

+2

@templatetypedef它实际上。他说'length'不是正常的字段,这就解释了'java.lang.NoSuchFieldException' ... – brimborium

+0

@ brimborium-有没有关于为什么'length'是“非正常字段?”的引用。根据JLS数组类型的作用,就好像“长度”被声明为公共字段一样,虽然字段代码对于字段查找是不同的,但是我找不到具体说明“数组长度不同”的任何内容。 – templatetypedef