77import java .lang .reflect .Method ;
88import java .lang .reflect .Modifier ;
99import java .util .ArrayList ;
10+ import java .util .HashMap ;
1011import java .util .HashSet ;
1112import java .util .List ;
13+ import java .util .Map ;
1214import java .util .Set ;
1315
1416/**
@@ -187,7 +189,7 @@ public static void set(Class clazz, Object instance, String variableName, Object
187189 * @param methodName The name of the method.
188190 * @return The invocation result, null if void.
189191 */
190- public static Object invokeMethod (Class clazz , Object instance , String methodName ) throws ReflectionException {
192+ public static < T > T invokeMethod (Class clazz , Object instance , String methodName ) throws ReflectionException {
191193 return invokeMethod (clazz , instance , methodName , new Class []{}, new Object []{});
192194 }
193195
@@ -202,7 +204,7 @@ public static Object invokeMethod(Class clazz, Object instance, String methodNam
202204 * @throws ReflectionException
203205 */
204206 @ SuppressWarnings ({"ThrowableInstanceNotThrown" , "ThrowableInstanceNeverThrown" })
205- public static Object invokeMethod (Object instance , String methodName , Object ... params ) throws ReflectionException {
207+ public static < T > T invokeMethod (Object instance , String methodName , Object ... params ) throws ReflectionException {
206208 Class c = instance .getClass ();
207209 Class [] argTypes ;
208210 {
@@ -235,7 +237,7 @@ public static Object invokeMethod(Object instance, String methodName, Object...
235237 }
236238 }
237239 m .setAccessible (true );
238- return m .invoke (instance , params );
240+ return ( T ) m .invoke (instance , params );
239241 }
240242 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex ) {
241243 throw new ReflectionException (ex );
@@ -258,13 +260,13 @@ public static Object invokeMethod(Object instance, String methodName, Object...
258260 * @throws ReflectionException
259261 */
260262 @ SuppressWarnings ({"ThrowableInstanceNotThrown" , "ThrowableInstanceNeverThrown" })
261- public static Object invokeMethod (Object instance , String methodName ) throws ReflectionException {
263+ public static < T > T invokeMethod (Object instance , String methodName ) throws ReflectionException {
262264 Class c = instance .getClass ();
263265 while (c != null ) {
264266 for (Method m : c .getDeclaredMethods ()) {
265- if (methodName .equals (m .getName ())) {
267+ if (methodName .equals (m .getName ()) && m . getParameterCount () == 0 ) {
266268 try {
267- return m .invoke (instance );
269+ return ( T ) m .invoke (instance );
268270 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex ) {
269271 throw new ReflectionException (ex );
270272 }
@@ -288,12 +290,12 @@ public static Object invokeMethod(Object instance, String methodName) throws Ref
288290 * @param args The arguments.
289291 * @return The invocation result, null if void.
290292 */
291- public static Object invokeMethod (Class clazz , Object instance , String methodName , Class [] argTypes , Object [] args )
293+ public static < T > T invokeMethod (Class clazz , Object instance , String methodName , Class [] argTypes , Object [] args )
292294 throws ReflectionException {
293295 try {
294296 Method m = clazz .getDeclaredMethod (methodName , argTypes );
295297 m .setAccessible (true );
296- return m .invoke (instance , args );
298+ return ( T ) m .invoke (instance , args );
297299 } catch (InvocationTargetException | NoSuchMethodException | IllegalArgumentException
298300 | IllegalAccessException | SecurityException ex ) {
299301 throw new ReflectionException (ex );
@@ -462,9 +464,8 @@ public static void throwUncheckedException(Throwable t) {
462464 *
463465 * @param className the fully qualified name of the desired class.
464466 * @return the {@code Class} object for the class with the specified name.
465- * @throws LinkageError if the linkage fails
466- * @throws ExceptionInInitializerError if the initialization provoked by this method fails
467- * @throws ReflectionException if the class cannot be located
467+ * @throws ReflectionException wraps a LinkageError if the linkage fails, ExceptionInInitializerError if the
468+ * initialization provoked by this method fails, or ClassNotFoundException if the class is not found.
468469 */
469470 public static Class forName (String className ) {
470471 try {
@@ -515,12 +516,11 @@ public static Class forName(String className) {
515516 * @param loader class loader from which the class must be loaded
516517 * @return class object representing the desired class
517518 *
518- * @throws LinkageError if the linkage fails
519- * @throws ExceptionInInitializerError if the initialization provoked by this method fails
520- * @throws ReflectionException if the class cannot be located by the specified class loader
521- * @throws SecurityException if a security manager is present, and the {@code loader} is {@code null}, and the
519+ * @throws ReflectionException wraps a LinkageError if the linkage fails, ExceptionInInitializerError if the
520+ * initialization provoked by this method fails, SecurityException if a security manager is present,
521+ * and the {@code loader} is {@code null}, and the
522522 * caller's class loader is not {@code null}, and the caller does not have the
523- * {@link RuntimePermission}{@code ("getClassLoader")}
523+ * {@link RuntimePermission}{@code ("getClassLoader")}, or ClassNotFoundException if the class is not found.
524524 *
525525 * @see java.lang.Class#forName(String, boolean, ClassLoader)
526526 * @see java.lang.ClassLoader
@@ -533,4 +533,26 @@ public static Class forName(String name, boolean initialize, ClassLoader loader)
533533 }
534534 }
535535
536+ // Exceptions are expensive, so cache this.
537+ private static Map <String , Boolean > classExistsMap = new HashMap <>();
538+
539+ /**
540+ * Checks if a class exists, according to Class.forName(). This is cached.
541+ * @param name The class name.
542+ * @return True if the class exists.
543+ */
544+ public static boolean classExists (String name ) {
545+ if (classExistsMap .containsKey (name )) {
546+ return classExistsMap .get (name );
547+ }
548+ try {
549+ Class .forName (name );
550+ classExistsMap .put (name , Boolean .TRUE );
551+ return true ;
552+ } catch (ClassNotFoundException ex ) {
553+ classExistsMap .put (name , Boolean .FALSE );
554+ return false ;
555+ }
556+ }
557+
536558}
0 commit comments