Last active
October 14, 2022 08:36
-
-
Save hugithordarson/a62062f8f78c11194537c67686f91493 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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