Skip to content

Instantly share code, notes, and snippets.

@hugithordarson
Last active October 14, 2022 08:36
Show Gist options
  • Save hugithordarson/a62062f8f78c11194537c67686f91493 to your computer and use it in GitHub Desktop.
Save hugithordarson/a62062f8f78c11194537c67686f91493 to your computer and use it in GitHub Desktop.
package x;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
public class KVCBastardization {
public static void main( String[] args ) throws Exception {
System.out.println( valueForKey( Collections.emptyList(), "size" ) );
System.out.println( valueForKey( List.of( "Item" ), "size" ) );
}
public static Object valueForKey( Object object, String key ) throws Exception {
return accessibleMethodForKey( object, key ).invoke( object );
}
private static Method accessibleMethodForKey( Object object, String key ) throws NoSuchMethodException, SecurityException {
Class<?> classToUseForLocatingMethod = object.getClass();
try {
while( classToUseForLocatingMethod != null ) {
Method classMethod = classToUseForLocatingMethod.getMethod( key );
if( classMethod.canAccess( object ) ) {
// This is the happy path, where we'll immediately end up in 99% of cases
return classMethod;
}
// Here come the dragons...
// The class doesn't have an accessible method definition. What about the interfaces?
for( Class<?> interfaceClass : classToUseForLocatingMethod.getInterfaces() ) {
try {
final Method interfaceMethod = interfaceClass.getMethod( key );
if( interfaceMethod.canAccess( object ) ) {
return interfaceMethod;
}
}
catch( Exception interfaceException ) {
// Failure to locate methods in interfaces are to be expected. If no interfaces contain the method, we've already failed anyway.
}
}
// Now let's try the whole thing again for the superclass
classToUseForLocatingMethod = classToUseForLocatingMethod.getSuperclass();
}
}
catch( NoSuchMethodException | SecurityException methodException ) {
// If the method doesn't exist on the original class we're dead whatever we do regardless of accessibility, so just throw immediately
throw methodException;
}
// FIXME: Throw, don't return null
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment