2
我正在寫一個測試庫,我希望能夠處理可能未提供自己的實現String toString()
的對象。如何判斷對象是否實現了類似toString()的方法?
在這些情況下,我寧願使用Apache Commons-Lang ToStringBuilder
而不是使用無用的默認實現,而寧願使用對象的實現toString()
(如果可用)。
如何判斷一個對象的默認實現是否爲toString()
?
我正在寫一個測試庫,我希望能夠處理可能未提供自己的實現String toString()
的對象。如何判斷對象是否實現了類似toString()的方法?
在這些情況下,我寧願使用Apache Commons-Lang ToStringBuilder
而不是使用無用的默認實現,而寧願使用對象的實現toString()
(如果可用)。
如何判斷一個對象的默認實現是否爲toString()
?
我發現,最好是使用java.lang.Class.getDeclaredMethod(String,Class<?>...)
並調用它的對象的類層次結構如下所示:
public static boolean objectHasToStringImplemented(final Object o){
return classHasToStringImplemented(o.getClass());
}
public static boolean classHasToStringImplemented(final Class<?> initialClass){
Class<?> classToCheck = initialClass;
while(classToCheck != Object.class){
if( classImplementsToString(classToCheck) ){
return true;
}
classToCheck = classToCheck.getSuperclass();
}
return false;
}
private boolean classImplementsToString(final Class<?> aClass){
try{
aClass.getDeclaredMethod("toString");
return true;
}catch(NoSuchMethodException e){
return false;
}
}
,然後我加速它通過緩存的答案,而不是引發異常
//NB: implementation is synchronized and thus thread-safe
private static final Hashtable<Class<?>,Boolean> cachedAnswers = new Hashtable<>();
static {
cachedAnswers.put(Object.class, Boolean.FALSE);
}
public static Boolean objectHasToStringImplemented(final Object o){
return classHasToStringImplemented(o.getClass());
}
public static Boolean classHasToStringImplemented(final Class<?> classToCheck){
if(cachedAnswers.containsKey(classToCheck) ){
return cachedAnswers.get(classToCheck);
}
final Boolean result = classImplementsToString(classToCheck) || classHasToStringImplemented(classToCheck.getSuperclass());
cachedAnswers.put(classToCheck, result);
return result;
}
private static Boolean classImplementsToString(final Class<?> aClass){
for(Method m : aClass.getDeclaredMethods()){
if( isToString(m) ){
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}
private static Boolean isToString(final Method m){
if( m.getParameterCount() == 0 && m.getName().equals("toString") && m.getReturnType().equals(String.class) ){
return Boolean.TRUE;
}else{
return Boolean.FALSE;
}
}
我已經測試了這個:
java.lang.StringBuilder
(它實現toString()
)java.util.ArrayList
(其繼承java.util.AbstractList
java.util.Objects
實現)(其僅具有靜態toString(java.lang.Object)
)String toString(int i)
方法定義NB:我還沒有用default
方法實現進行測試,因爲我目前沒有訪問Java 8 JRE的權限。