I want to write a method that checks if given object contains fields of null value. What I've written works fine BUT the problem occurs with primitive types.
public static <T> List<String> checkIfNullsInObject(T ob) {
List<String> fieldsAsNull = new LinkedList<>();
for (Field f : ob.getClass().getDeclaredFields()) {
f.setAccessible(true);
try {
if (Objects.isNull(f.get(ob))) {
fieldsAsNull.add(f.getName());
}
} catch (Exception e) {
e.getMessage();
e.printStackTrace();
}
}
return fieldsAsNull;
}
so eg.
class Dog:
public class Dog {
private String name;
private int age;
private String owner;
///set get
}
given Object :
Dog dog = new Dog();
// dog.setAge(44);
// dog.setName("Maniek");
// dog.setOwner("AZE");
the method should return "age , name ,owner", but it only returns two last one. I know that int is set to 0, and therfore it is not considered as null because of beeing primitive type and not a refrence to null.
The java doc about Field.get(Object o) method says :
Returns the value of the field represented by this Field, on the specified object. The value is automatically wrapped in an object if it has a primitive type.
If it's wrapped to object I'd expect it to return null, not zero what am I missing here? Is it unwrapped once again somewhere in between?
/////////////////////////////////////////////////////
I knew that changing type to Wrapper class would do the job, but I'm not sure if changing another class because of adding another class is good practice therefore I've decided to do soemthing like this:
public static <T> void checkIfNullsInObject(T ob) throws DataInputException {
try {
for (Field f : ob.getClass().getDeclaredFields()) {
f.setAccessible(true);
if (Objects.isNull(f.get(ob)) || checkForZeroPrimitives(ob, f))
throw new DataInputException("Can not update entity with field \""
+ f.getName() + "\" set to: " + f.get(ob));
}
} catch (IllegalArgumentException |IllegalAccessException e) {
e.getMessage();
e.printStackTrace();
}
}
private static <T> boolean checkForZeroPrimitives(T ob, Field field) throws IllegalArgumentException, IllegalAccessException {
if (field.getType().getName().equals("int") && field.getInt(ob) == 0)
return true;
if (field.getType().getName().equals("double") && field.getDouble(ob) == 0.0)
return true;
if (field.getType().getName().equals("float") && field.getFloat(ob) == 0)
return true;
if (field.getType().getName().equals("long") && field.getLong(ob) == 0)
return true;
if (field.getType().getName().equals("short") && field.getShort(ob) == 0)
return true;
if (field.getType().getName().equals("byte") && field.getByte(ob) == 0)
return true;
if (field.getType().getName().equals("char") && field.getChar(ob)=='\u0000')
return true;
return false;
}
later on I intend to improve the -if ladder.
age
is 0, so the wrapped value is anInteger
with a value of 0. If you're expecting to be able to tell the difference between having calleddog.setAge(0);
and not having called anything, then you need a different field type.int
loads with the default value of0
then when you wrap it in anInteger
class it will still be0
...