java Java如何使用反射检查字段是否已初始化或是否为默认值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7223482/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 19:10:25  来源:igfitidea点击:

Java how can I with reflection check if a field is initialized or is default value?

javareflection

提问by rapadura

So, should be straight forward question.

所以,应该是直截了当的问题。

Lets say I have a class with a lot of fields like:

假设我有一个包含很多字段的类,例如:

String thizz;
long that;
boolean bar;

How can I, with reflection, see if the fields thizz, thatand barhave been initialized or left to their default values of null, 0 and false?

我如何通过反射查看字段thizz,thatbar是否已初始化或保留为它们的默认值 null、0 和 false?

回答by Peter Lawrey

You have only 7 primitive types and one reference type to check. If you group all Number types together, you only have four values to check for.

您只有 7 种基本类型和一种引用类型需要检查。如果将所有 Number 类型组合在一起,则只有四个值需要检查。

Object o =
for (Field field : o.getClass().getDeclaredFields()) {
 Class t = field.getType();
 Object v = field.get(o);
 if(t == boolean.class && Boolean.FALSE.equals(v)) 
   // found default value
 else if(t == char.class && ((Character) v).charValue() == 0)
   // found default value
 else if(t.isPrimitive() && ((Number) v).doubleValue() == 0)
   // found default value
 else if(v == null)
   // found default value
}  

回答by Jeffrey

You don't need reflection...

你不需要反思...

if (thizz == null) {
    //it's not initialized
}
if (that == 0) {
   //it's not initialized
}
if(bar == false) {
    //it's not initialized
}

However, they could have been initialized then reset to their default values. If you truly want to know if they're been initialized you could do something like this:

但是,它们可以被初始化然后重置为它们的默认值。如果您真的想知道它们是否已初始化,您可以执行以下操作:

private boolean isFooInitialized = false;
private Foo foo;
public void setFoo(Foo foo) {
    this.foo = foo;
    isFooInitialized = foo != null;
}

/edit To get all the fields from a class, check out Class.getDeclaredFields(). This will give every field, not just the public ones.

/edit 要从类中获取所有字段,请查看Class.getDeclaredFields()。这将提供每个领域,而不仅仅是公共领域。

From here you can check the type of the field and get its value:

从这里您可以检查字段的类型并获取其值:

Foo foo = ...
Field[] fooFields = foo.getClass().getDeclaredFields();
for (Field fooField : fooFields) {
    Class<?> fooFieldClass = fooField.getClass();
    if (fooFieldClass.equals(int.class)) {
        if (fooField.getInt(foo) == 0) {
            // not initialized
        }
    } else if (fooFieldClass.equals(double.class)) {
        if (fooField.getDouble(foo) == 0) {
            // not initialized
        }
    } else if (fooFieldClass.equals(boolean.class)) {
        if (fooField.getBoolean(foo) == false) {
            // not initialized
        }
    } else if (fooFieldClass.equals(float.class)) {
        if (fooField.getFloat(foo) == 0) {
            // not initialized
        }
    } else if (fooFieldClass.equals(char.class)) {
        if (fooField.getChar(foo) == 0) {
            // not initialized
        }
    } else if (fooFieldClass.equals(byte.class)) {
        if (fooField.getByte(foo) == 0) {
            // not initialized
        }
    } else if (fooFieldClass.equals(long.class)) {
        if (fooField.getLong(foo) == 0) {
            // not initialized
        }
    } else if (fooField.get(foo) == null) {
        // not initialized
    }
}

回答by Christophe Weis

Peter Lawrey's answerworks fine for me, except for fields of primitive data type char, which raises the following exception in my code :

Peter Lawrey 的回答对我来说很好,除了原始数据类型的字段char,这会在我的代码中引发以下异常:

java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number

So I added the charcase :

所以我添加了char案例:

Object o =
for (Field field : o.getClass().getDeclaredFields()) {
 Class t = field.getType();
 Object v = field.get(o);
 if (boolean.class.equals(t) && Boolean.FALSE.equals(v)) 
   // found default value
 else if (char.class.equals(t) && ((Character) v) != Character.MIN_VALUE)
   // found default value
 else if (t.isPrimitive() && ((Number) v).doubleValue() == 0)
   // found default value
 else if(!t.isPrimitive() && v == null)
   // found default value
}  

Character.MIN_VALUEis '\u0000', which is the default value of characcording to the Java Documentation on primitive data types.

Character.MIN_VALUEis '\u0000',这是char根据关于原始数据类型Java 文档的默认值。

回答by JB Cha

You can create a new instance via reflection (automatically initialized with default value) and compare yourObject with this default instance.

您可以通过反射创建一个新实例(使用默认值自动初始化)并将 yourObject 与此默认实例进行比较。

//default Object filled with default values:
Object defaultObject = yourObject.getClass().newInstance();
for (final Field field : yourObject.getClass().getDeclaredFields()) {
  final Object value = field.get(yourObject);
  if (value == null || value.equals(field.get(defaultObject))) {
    // found default value
  }
}

PS: This solution also solved the issue with char mentioned by Christophe Weis.

PS:这个解决方案也解决了 Christophe Weis 提到的 char 问题。

回答by Preston

This should get you going in the right direction.

这应该让你朝着正确的方向前进。

    Class clazz = Class.forName("your.class");
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
      String dataType = field.getType().getName();
      if (dataType.equals("java.lang.String")) {
          System.out.println("found a string");
      }
    }

回答by david van brink

The gist of it is:

它的要点是:

Field[] fields = yourObject.getClass().getFields();
for(Field f : fields)
{
  Class<?> k = f.getType();
  // depending on k, methods like f.getInt(yourObject),
  // f.getFloat(yourObject), 
  // f.getObject(hourObject) to get each member.
}

Now, this only lets you read the public fields.

现在,这只允许您读取公共字段。

Alternatively, IF your object follows getX/setX naming conventions, you can use getMethods(), and look for methods named "getXxx" and "setXxx", to infer the existence of settable fields -- and invoke those getters to look for the expected default values.

或者,如果您的对象遵循 getX/setX 命名约定,您可以使用 getMethods(),并查找名为“getXxx”和“setXxx”的方法,以推断可设置字段的存在——并调用这些 getter 来查找预期的默认值。