简体   繁体   English

使用反射确定字段是否为我创建的类型

[英]Determine if a field is a type I created, using reflection

Assuming I have an object and I took it fields: 假设我有一个对象,并将其带入字段:

Field[] fields = obj.getFields();

Now I'm iterating through each one and would like to print their members if it's some kind of class, otherwise just use field.get(obj) in case it's a string, int or anything that this command will print its value, not just the reference pointer. 现在,我要遍历每个对象,如果是某种类,则希望打印其成员,否则,如果它是字符串,int或此命令将打印其值的任何东西,则仅使用field.get(obj) ,而不仅仅是参考指针。

How can I detect it? 如何检测到它?

You can get, without instantiation required, the Type of each field of a class like this: 您可以在不需要实例化的情况下获得此类的每个字段的Type

public class GetFieldType {

    public static void main (String [] args) {
        Field [] fields = Hello.class.getFields();

        for (Field field: fields) {
            System.out.println(field.getGenericType());
        }
    }

    public static class Hello {
        public ByeBye bye;
        public String message;
        public Integer b;
        ...
    }
}

You can use instanceof to tell the objects apart. 您可以使用instanceof区分对象。

public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
    Object[] objects = new Object[4];
    objects[0] = new Integer(2);
    objects[1] = "StringTest";
    objects[2] = new BigDecimal(2.00d);
    for (Object obj : objects) {
        if (obj != null) {
            if (obj instanceof BigDecimal) {
                System.out.println("bigdecimal found " + obj);
            } else if (obj instanceof String) {
                System.out.println("String found " + obj);
            } else {
                System.out.println("Integer found " + obj);
            }
        }
        else{
            System.out.println("object is null");
        }
    }
}

If you need to test if an object is from your project, you can look at the package name and compare it to your project's package name. 如果需要测试对象是否来自项目,则可以查看程序包名称并将其与项目的程序包名称进行比较。

You can either do this on the declared type of the field or on the runtime type of the field contents. 您可以在字段的声明类型或字段内容的运行时类型上执行此操作。 The snippet below demonstrates the latter approach: 下面的代码段演示了后一种方法:

SomeClass foo = new SomeClass();

for (Field f : foo.getClass().getDeclaredFields()) {

  boolean wasAccessible = f.isAccessible();
  try {
    f.setAccessible(true);
    Object object = f.get(foo);

    if (object != null) {

      if (object.getClass().getPackage().getName()
          .startsWith("your.project.package")) {
        // one of yours
      }
    } else {
      // handle a null value
    }
  } finally {
    f.setAccessible(wasAccessible);
  }
}

Do remember that obj.getFields(); 请记住, obj.getFields(); only returns publicly-accessible fields. 仅返回可公开访问的字段。 You may want to consider getDeclaredFields() as I've done above. 您可能需要像上面所做的那样考虑getDeclaredFields() If you stick with getFields() , you can omit the accessibility code in the above example. 如果坚持使用getFields() ,则可以在上面的示例中省略可访问性代码。

With a bit of work, you could distinguish your classes by the classloader that loaded them. 通过一些工作,您可以通过加载它们的类加载器来区分您的类。 Take a look at this: 看看这个:

Find where java class is loaded from 查找从何处加载Java类

Though this could help, it's not going to be the silver bullet for your problem, mainly because: 尽管这可能有所帮助,但这并不是解决问题的灵丹妙药,主要是因为:

  • primitives (byte, short, char, int, long, float, double, and boolean) are not classes. 基元(byte,short,char,int,long,float,double和boolean)不是类。
  • the architecture of classloaders is different in different app servers. 在不同的应用服务器中,类加载器的体系结构是不同的。
  • the same class could be loaded many times by different classloaders. 同一类可以由不同的类加载器多次加载。

what I understood is you what to go recursive in object hierarchy and get values of primitives 我了解的是您要在对象层次结构中递归并获取基元的值

public class ParentMostClass {
   int a = 5;
   OtherClass other = new OtherClass();

   public static void main(String[] args) throws IllegalArgumentException,
    IllegalAccessException {
      ParentMostClass ref = new ParentMostClass();
      printFiledValues(ref);
  }

public static void printFiledValues(Object obj)
    throws IllegalArgumentException, IllegalAccessException {

    Class<? extends Object> calzz = obj.getClass();
    Field[] fileds = obj.getClass().getDeclaredFields();

    for (Field field : fileds) {
        Object member = field.get(obj);
        // you need to handle all primitive, they are few
        if (member instanceof String || member instanceof Number) {
            System.out.println(calzz + "->" + field.getName() + " : "
            + member);
        } else {
           printFiledValues(member);
    }
  }
}
}

public class OtherClass {
    int b=10;
}

I got output as 我得到了输出

class com.example.ParentMostClass->a : 5
class com.example.OtherClass->b : 10

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用反射确定字段类型是否为列表(或任何其他类型的集合)? - how to determine whether a field type is a List (or any other type of collections) using reflection? 使用反射,我可以确定Java静态最终字段是否内联? - Using reflection, can I determine if a Java static final field will be in-lined? 使用反射获取字段的泛型类型 - Obtain generic type of a Field using reflection 如何获取类型内的字段(<t> ) 在 Java 上使用反射的实现中</t> - How can I get a field inside a type (<T>) inside an implementation using Reflection on Java 使用Java反射,我可以访问类型为private静态嵌套类的private字段吗? - Using Java reflection, can I access a private field of type private static nested class? 如何获取使用反射为其创建收集对象的类类型 - How to get the class type for which a collection object is created using reflection 如何确定字段的未删除类型? - How can I determine the unerased type of a field? 如何使用 Java 反射设置具有不同数字类型的数字字段 - How to set a Number field with a different Number type using Java Reflection 如何使用 java 反射迭代列表类型的字段 - How to iterate Field of type List using java reflection 如何使用反射 API 以相同的顺序获取字段类型和值? - How to get field type and value in same order using Reflection API?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM