我正在编写测试库,我希望能够处理可能没有提供自己的String toString()
实现的对象。
在这些情况下,而不是使用无用的默认实现,我想使用Apache Commons-Lang ToStringBuilder
代替......但是如果可用的话,宁愿使用对象的toString()
实现。
如何确定对象是否具有toString()
除默认值以外的实现?
答案 0 :(得分:1)
我发现的最好的方法是使用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。