【问题标题】:Getting fields information using java reflection使用java反射获取字段信息
【发布时间】:2014-03-10 09:57:10
【问题描述】:

我正在开发这个程序,它将打印与对象相关的所有信息,这些信息包括:

对于 x 中的每个切片(对象层次结构中的类):

  • 打印切片的类名。

  • 对于该切片中的每个非静态字段:

    • 打印所有字段修饰符,后跟字段名称。
    • 打印字段值如下:
      • 如果字段为 null,则打印 null。
      • 如果字段是原始类型,则打印其值
      • 如果字段是字符串,则打印其值
      • 如果字段是数组:
        • 循环遍历数组中的元素
        • 打印索引
        • 递归打印数组项的详细信息
      • 否则,递归打印字段的详细信息

我已经使用下面的代码打印了几乎所有的信息:

public void print(Object obj) {
        Class cl = obj.getClass();
        while(cl != null) {
            System.out.println("Class Name: " + cl.getName());
            Field[] fields = cl.getFields();
            System.out.println("FIELDS: ");
            for(int i=0; i<fields.length; i++) {
                String modifier = Modifier.toString(fields[i].getModifiers());
                String name = fields[i].getName();
                System.out.print("Modifier: "+modifier+" Name: "+name+ "  ");
                try {
                    if(fields[i].get(cl) == null)
                        System.out.print("Value: NULL");
                } catch (        IllegalArgumentException | IllegalAccessException ex) {
                    Logger.getLogger(JCP.class.getName()).log(Level.SEVERE, null, ex);
                }
                if(fields[i].getType().isPrimitive())
                    try {
                        System.out.println("Value: " + fields[i].get(cl));
                } catch (        IllegalArgumentException | IllegalAccessException ex) {
                    Logger.getLogger(JCP.class.getName()).log(Level.SEVERE, null, ex);
                }
                if(fields[i].getType().isArray()) {
                    try {
                        Object[] object=(Object[])fields[i].get(obj);
                        System.out.print("Values: ");
                        for(int j=0;j<object.length;j++){
                            System.out.print(object[j].toString() + ",");
                        }   } catch (            IllegalArgumentException | IllegalAccessException ex) {
                        Logger.getLogger(JCP.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
            System.out.println();
            cl = cl.getSuperclass();
        } 
    }

在以下课程上进行测试:

public class hello {
    private int privateField1;
    private long privateField2;
    public int publicField1;
    public int publicField2;

    public hello() {
    }


}

我得到以下输出:

Class Name: hello
FIELDS: 
Mar 10, 2014 2:54:36 PM JCP print
SEVERE: null
java.lang.IllegalArgumentException: Can not set int field hello.publicField1 to java.lang.Class
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
Modifier: public Name: publicField1  Modifier: public Name: publicField2  
Class Name: java.lang.Object
FIELDS: 

    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
    at sun.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56)
    at sun.reflect.UnsafeIntegerFieldAccessorImpl.get(UnsafeIntegerFieldAccessorImpl.java:36)
    at java.lang.reflect.Field.get(Field.java:379)
    at JCP.print(JCP.java:211)
    at JCP.start(JCP.java:36)
    at Main.main(Main.java:11)

Mar 10, 2014 2:54:36 PM JCP print
SEVERE: null
java.lang.IllegalArgumentException: Can not set int field hello.publicField1 to java.lang.Class
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
    at sun.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56)
    at sun.reflect.UnsafeIntegerFieldAccessorImpl.get(UnsafeIntegerFieldAccessorImpl.java:36)
    at java.lang.reflect.Field.get(Field.java:379)
    at JCP.print(JCP.java:219)
    at JCP.start(JCP.java:36)
    at Main.main(Main.java:11)

Mar 10, 2014 2:54:36 PM JCP print
SEVERE: null
java.lang.IllegalArgumentException: Can not set int field hello.publicField2 to java.lang.Class
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
    at sun.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56)
    at sun.reflect.UnsafeIntegerFieldAccessorImpl.get(UnsafeIntegerFieldAccessorImpl.java:36)
    at java.lang.reflect.Field.get(Field.java:379)
    at JCP.print(JCP.java:211)
    at JCP.start(JCP.java:36)
    at Main.main(Main.java:11)

Mar 10, 2014 2:54:36 PM JCP print
SEVERE: null
java.lang.IllegalArgumentException: Can not set int field hello.publicField2 to java.lang.Class
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
    at sun.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56)
    at sun.reflect.UnsafeIntegerFieldAccessorImpl.get(UnsafeIntegerFieldAccessorImpl.java:36)
    at java.lang.reflect.Field.get(Field.java:379)
    at JCP.print(JCP.java:219)
    at JCP.start(JCP.java:36)
    at Main.main(Main.java:11)

主要是在“fields[i].get(cl)”中抛出所有异常,请帮助我找出获取字段值的问题所在。

【问题讨论】:

    标签: java reflection


    【解决方案1】:

    你必须使用:

    fields[i].get(obj)
    

    代替:

    fields[i].get(cl)
    

    因为您试图获取类的这个特定实例的值,而不是类本身。

    【讨论】:

    • 好吧,但是类将在循环中不断变化(在层次结构中向上),并且 obj 将只是初始类的一个对象。我必须先制作每个班级的对象还是什么?
    • @AbdulJabbar obj 是初始类的一个实例,但它也是这个类的所有超类的一个实例,所以你只需使用obj 来处理所有事情,它就可以工作。
    • 谢谢,它成功了。你能在“如果字段是字符串”部分帮助我吗?无论如何都找不到像 isString() 这样的东西。
    • @AbdulJabbar if(fields[i].getType().equals(String.class)) 应该可以工作。
    【解决方案2】:

    您在这部分的代码中几乎没有问题

    if(fields[i].get(cl) == null) {
        System.out.print("Value: NULL");
    }
    
    if(fields[i].getType().isPrimitive()) {
        System.out.println("Value: " + fields[i].get(cl));
    }
    
    if(fields[i].getType().isArray()) {
        Object[] object=(Object[])fields[i].get(obj);
        System.out.print("Values: ");
    
        for(int j=0;j<object.length;j++){
            System.out.print(object[j].toString() + ",");
        }
    }
    

    拳头是你在类型实例而不是类上调用方法。

    fields[i].get(obj) 应该是 fields[i].get(cl),当您检查私有值时,您会重复这一点。你也习惯了很多调用。如果将结果分配给局部变量,则可以简化代码的可读性。

    public void print(Object obj) throws IllegalArgumentException, IllegalAccessException {
    
            Class type = obj.getClass();
    
            while(type != null) {
    
                System.out.printf("Class Name: %s ", type.getName());
                System.out.println("FIELDS: ");
    
                for(Fiedl field : type.getFields()) {
    
                    String modifier = Modifier.toString(field.getModifiers());
    
                    String name = field.getName();
    
                    System.out.printf("Modifiers: %s Name:%s\n",modifier,name);
    
                    Object   fieldValue = field.get(obj);
                    Class<?> filedType  = field.getType();
                    String   printValue = null;
    
                    if(fieldValue == null) {
                         printValue = "NULL";
                    } else 
                    if(fieldType.isArray()) {
                         printValue = Arrays.toString((Object[]) fieldValue);
                    } else {
                         printValue = String.valueOf(fieldValue);                
                    }
    
                    System.out.printf("Value: %s",printValue);
    
                }
                System.out.println();
                type = type.getSuperclass();
            } 
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-08
      • 2013-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      相关资源
      最近更新 更多