For getter method who has no parameter , try this:
Util.isNull(person, "getDetails().iterator().next().getName().getFullName()")
for most of the cases, it works well. Basically, it is trying to use java reflection to do the null check layer by layer, till it reach the last getter method , since we do a lot cacheing for the
reflection, the code works well in production. Please check the code below.
public static boolean isNull(Object obj, String methods) {
if (Util.isNull(obj)) {
return true;
}
if (methods == null || methods.isEmpty()) {
return false;
}
String[] A = methods.split("\\.");
List<String> list = new ArrayList<String>();
for (String str : A) {
list.add(str.substring(0, str.indexOf("(")).trim());
}
return isNullReflect(obj, list);
}
public static boolean isNullReflect(Object obj, List<String> methods) {
if (Util.isNull(obj)) {
return true;
}
if (methods.size() == 0) {
return obj == null;
}
Class<?> className = Util.getClass(obj);
try {
Method method = Util.getMethod(className.getName(), methods.remove(0), null, className);
method.setAccessible(true);
if (method.getName().equals("next")
&& !Util.isNull(Util.getMethod(className.getName(), "hasNext", null, className))) {
if (!((Iterator<?>) (obj)).hasNext()) {
return true;
}
}
try {
return isNullReflect(method.invoke(obj), methods);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public static Boolean isNull(Object object) {
return null == object;
}
public static Method getMethod(String className, String methodName, Class<?>[] classArray, Class<?> classObj) {
// long a = System.nanoTime();
StringBuilder sb = new StringBuilder();
sb.append(className);
sb.append(methodName);
if (classArray != null) {
for (Class<?> name : classArray) {
sb.append(name.getName());
}
}
String methodKey = sb.toString();
Method result = null;
if (methodMap.containsKey(methodKey)) {
return methodMap.get(methodKey);
} else {
try {
if (classArray != null && classArray.length > 0) {
result = classObj.getMethod(methodName, classArray);
} else {
result = classObj.getMethod(methodName);
}
methodMap.put(methodKey, result);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// long b = System.nanoTime();
// counter += (b - a);
return result;
}
private static Map<String, Method> methodMap = new ConcurrentHashMap<String, Method>();
is
null, and return from the method in that case. This avoids the deep nesting of scopes (which I find hard to read, usually). – Rubbery