所以,这应该是一个简单的问题。
假设我有一个具有许多字段的类,例如:
String thizz;
long that;
boolean bar;
我如何使用反射机制判断字段thizz
,that
和bar
是否已被初始化或留在它们的默认值null、0和false?
所以,这应该是一个简单的问题。
假设我有一个具有许多字段的类,例如:
String thizz;
long that;
boolean bar;
我如何使用反射机制判断字段thizz
,that
和bar
是否已被初始化或留在它们的默认值null、0和false?
你只需要检查7种基本类型和1种引用类型。如果将所有数字类型分组在一起,则只需检查4个值。
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
}
char
怎么办?(Character
不是一个 Number
) - DodgyCodeExceptionchar
是一个无符号的16位值。例如,你可以写成 char ch = 48;
或者 Character ch = 48;
或者 char ch = '0'; ch /= 0.9;
在初始化之前它是 0
或者 '\0'
。 - Peter Lawreyelse if(t.isPrimitive() && ((Number) v).doubleValue() == 0)
中获得 ClassCastException,因为 v 是 Character 类,无法转换为 Number。 - DodgyCodeExceptionPeter Lawrey的回答 对我很有帮助,除了原始数据类型char
的字段外,在我的代码中会引发以下异常:
java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number
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_VALUE
是 '\u0000'
,根据Java基本数据类型文档,这是 char
的默认值。
if (thizz == null) {
//it's not initialized
}
if (that == 0) {
//it's not initialized
}
if(bar == false) {
//it's not initialized
}
然而,它们可以被初始化然后重置为默认值。如果您真的想知道它们是否已被初始化,您可以像这样做:
private boolean isFooInitialized = false;
private Foo foo;
public void setFoo(Foo foo) {
this.foo = foo;
isFooInitialized = foo != null;
}
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
}
}
bool IsDefault(bool b)
, bool IsDefault(long i)
, 等等(某些类型可以重复使用,如int/long
和float/double
),根据需要修改反射。 - user166390//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: 这个解决方案还解决了Christophe Weis提到的关于字符的问题。
Foo
。
可以这样做:Object defaultObject = yourObject.getClass().newInstance();
(如果获取所有构造函数并创建具有最少参数的构造函数,则可以更加精细)。 - Hash这应该让你朝着正确的方向前进。
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");
}
}
它的要点是:
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.
}
现在,这只允许您读取公共字段。
或者,如果您的对象遵循getX/setX命名约定,您可以使用getMethods(),并查找名为“getXxx”和“setXxx”的方法,以推断可设置字段的存在--并调用那些getter来查找预期的默认值。
getFields()
仅返回公共字段。 - Paul BelloragetDeclaredFields()
会返回所有字段。 - Matthieu
Boolean
的默认值是null
。也许您想要使用的是boolean
类型? - BalusC