diff --git a/src/main/java/net/jodah/typetools/TypeResolver.java b/src/main/java/net/jodah/typetools/TypeResolver.java index 48e5f70..ad5847a 100644 --- a/src/main/java/net/jodah/typetools/TypeResolver.java +++ b/src/main/java/net/jodah/typetools/TypeResolver.java @@ -308,7 +308,7 @@ private static void populateLambdaArgs(Class functionalInterface, final Class // Get functional interface's type params Type returnTypeVar = m.getGenericReturnType(); Type[] paramTypeVars = m.getGenericParameterTypes(); - + // Get lambda's type arguments ConstantPool constantPool = (ConstantPool) GET_CONSTANT_POOL.invoke(lambdaType); String[] methodRefInfo = constantPool @@ -330,19 +330,27 @@ private static void populateLambdaArgs(Class functionalInterface, final Class } TypeDescriptor[] arguments = TypeDescriptor.getArgumentTypes(methodRefInfo[2]); - + // Handle arbitrary object instance method references - int offset = 0; + int paramOffset = 0; if (paramTypeVars[0] instanceof TypeVariable && paramTypeVars.length == arguments.length + 1) { Class instanceType = TypeDescriptor.getObjectType(methodRefInfo[0]) .getType(lambdaType.getClassLoader()); map.put((TypeVariable) paramTypeVars[0], instanceType); - offset = 1; + paramOffset = 1; } - for (int i = 0; i < arguments.length; i++) - if (paramTypeVars[i + offset] instanceof TypeVariable) - map.put((TypeVariable) paramTypeVars[i + offset], arguments[i].getType(lambdaType.getClassLoader())); + // Handle local final variables from context that are passed as arguments. + int argOffset = 0; + if(paramTypeVars.length < arguments.length ) { + argOffset = arguments.length - paramTypeVars.length; + } + + for(int i = 0; i + argOffset < arguments.length; i++) { + if (paramTypeVars[i] instanceof TypeVariable) { + map.put((TypeVariable) paramTypeVars[i + paramOffset], arguments[i + argOffset].getType(lambdaType.getClassLoader())); + } + } break; } } diff --git a/src/test/java/net/jodah/typetools/functional/LambdaTest.java b/src/test/java/net/jodah/typetools/functional/LambdaTest.java index 02cc967..2f7a084 100644 --- a/src/test/java/net/jodah/typetools/functional/LambdaTest.java +++ b/src/test/java/net/jodah/typetools/functional/LambdaTest.java @@ -4,6 +4,7 @@ import java.util.Comparator; import java.util.UUID; +import java.util.concurrent.atomic.AtomicLong; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.BiPredicate; @@ -103,6 +104,18 @@ public void shouldResolveArguments() { assertEquals(TypeResolver.resolveRawArgument(Consumer.class, consumer.getClass()), String.class); } + public void shouldResolveArgumentsCorrectly() { + + final AtomicLong a = new AtomicLong(0); + Function func = (s) -> { + a.incrementAndGet(); + return (long)s.hashCode(); + }; + + assertEquals(new Class[] {String.class, Long.class}, TypeResolver.resolveRawArguments(Function.class, func.getClass())); + + } + /** * Asserts that arguments can be resolved from method references for simple functional interfaces. */