Reputation: 5300
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
, that
and bar
have been initialized or left to their default values of null, 0 and false?
Upvotes: 13
Views: 27556
Reputation: 533520
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.
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
}
Upvotes: 22
Reputation: 597
You can create a new instance via reflection (automatically initialized with default value) and compare yourObject with this default instance.
//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.
Upvotes: 6
Reputation: 2664
Peter Lawrey's answer works fine for me, except for fields of primitive data type char
, which raises the following exception in my code :
java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number
So I added the char
case :
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
is '\u0000'
, which is the default value of char
according to the Java Documentation on primitive data types.
Upvotes: 8
Reputation: 44808
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.
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
}
}
Upvotes: 6
Reputation: 3642
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.
Upvotes: 1
Reputation: 3271
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");
}
}
Upvotes: 1