Java如何使用反射检查字段是初始化还是默认值?

rap*_*ura 9 java reflection

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

可以说我有一个课程,有很多领域,如:

String thizz;
long that;
boolean bar;
Run Code Online (Sandbox Code Playgroud)

我怎样才能与反思,看是否领域thizz,thatbar已初始化或离开NULL,0和虚假的默认值吗?

Pet*_*rey 21

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

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
}  
Run Code Online (Sandbox Code Playgroud)


Jef*_*rey 6

你不需要反思......

if (thizz == null) {
    //it's not initialized
}
if (that == 0) {
   //it's not initialized
}
if(bar == false) {
    //it's not initialized
}
Run Code Online (Sandbox Code Playgroud)

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

private boolean isFooInitialized = false;
private Foo foo;
public void setFoo(Foo foo) {
    this.foo = foo;
    isFooInitialized = foo != null;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*eis 6

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

java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number
Run Code Online (Sandbox Code Playgroud)

所以我添加了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
}  
Run Code Online (Sandbox Code Playgroud)

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


JB *_*Cha 6

您可以通过反射创建一个新实例(使用默认值自动初始化)并将 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
  }
}
Run Code Online (Sandbox Code Playgroud)

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