How would you check if a String was a number before parsing it?
Here was my answer to the problem.
A catch all convenience method which you can use to parse any String with any type of parser: isParsable(Object parser, String str)
. The parser can be a Class
or an object
. This will also allows you to use custom parsers you've written and should work for ever scenario, eg:
isParsable(Integer.class, "11");
isParsable(Double.class, "11.11");
Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");
Here's my code complete with method descriptions.
import java.lang.reflect.*;
/**
* METHOD: isParsable
*
* This method will look through the methods of the specified from
parameter
* looking for a public method name starting with "parse" which has only one String
* parameter.
*
* The parser
parameter can be a class or an instantiated object, eg:
* Integer.class
or new Integer(1)
. If you use a
* Class
type then only static methods are considered.
*
* When looping through potential methods, it first looks at the Class
associated
* with the parser
parameter, then looks through the methods of the parent's class
* followed by subsequent ancestors, using the first method that matches the criteria specified
* above.
*
* This method will hide any normal parse exceptions, but throws any exceptions due to
* programmatic errors, eg: NullPointerExceptions, etc. If you specify a parser
* parameter which has no matching parse methods, a NoSuchMethodException will be thrown
* embedded within a RuntimeException.
*
* Example:
* isParsable(Boolean.class, "true");
* isParsable(Integer.class, "11");
* isParsable(Double.class, "11.11");
* Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
* isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");
*
*
* @param parser The Class type or instantiated Object to find a parse method in.
* @param str The String you want to parse
*
* @return true if a parse method was found and completed without exception
* @throws java.lang.NoSuchMethodException If no such method is accessible
*/
public static boolean isParsable(Object parser, String str) {
Class theClass = (parser instanceof Class? (Class)parser: parser.getClass());
boolean staticOnly = (parser == theClass), foundAtLeastOne = false;
Method[] methods = theClass.getMethods();
// Loop over methods
for (int index = 0; index < methods.length; index++) {
Method method = methods[index];
// If method starts with parse, is public and has one String parameter.
// If the parser parameter was a Class, then also ensure the method is static.
if(method.getName().startsWith("parse") &&
(!staticOnly || Modifier.isStatic(method.getModifiers())) &&
Modifier.isPublic(method.getModifiers()) &&
method.getGenericParameterTypes().length == 1 &&
method.getGenericParameterTypes()[0] == String.class)
{
try {
foundAtLeastOne = true;
method.invoke(parser, str);
return true; // Successfully parsed without exception
} catch (Exception exception) {
// If invoke problem, try a different method
/*if(!(exception instanceof IllegalArgumentException) &&
!(exception instanceof IllegalAccessException) &&
!(exception instanceof InvocationTargetException))
continue; // Look for other parse methods*/
// Parse method refuses to parse, look for another different method
continue; // Look for other parse methods
}
}
}
// No more accessible parse method could be found.
if(foundAtLeastOne) return false;
else throw new RuntimeException(new NoSuchMethodException());
}
/**
* METHOD: willParse
*
* A convienence method which calls the isParseable method, but does not throw any exceptions
* which could be thrown through programatic errors.
*
* Use of {@link #isParseable(Object, String) isParseable} is recommended for use so programatic
* errors can be caught in development, unless the value of the parser
parameter is
* unpredictable, or normal programtic exceptions should be ignored.
*
* See {@link #isParseable(Object, String) isParseable} for full description of method
* usability.
*
* @param parser The Class type or instantiated Object to find a parse method in.
* @param str The String you want to parse
*
* @return true if a parse method was found and completed without exception
* @see #isParseable(Object, String) for full description of method usability
*/
public static boolean willParse(Object parser, String str) {
try {
return isParsable(parser, str);
} catch(Throwable exception) {
return false;
}
}