Skip to content

Instantly share code, notes, and snippets.

@aslakhellesoy
Last active August 29, 2015 14:05
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aslakhellesoy/3678beba60c109eacbe5 to your computer and use it in GitHub Desktop.
Save aslakhellesoy/3678beba60c109eacbe5 to your computer and use it in GitHub Desktop.
package lambdas;
import sun.reflect.ConstantPool;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class TypeTest {
@FunctionalInterface
public static interface Block<A> {
public void call(A arg);
}
private static final Method getConstantPool;
static {
try {
getConstantPool = Class.class.getDeclaredMethod("getConstantPool");
getConstantPool.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public static <A> void instantitesLambdaArgBasedOnGenericType(Block<A> block) throws Exception {
Type genericInterface = block.getClass().getGenericInterfaces()[0];
if (genericInterface instanceof ParameterizedType) {
Class<A> type = (Class<A>) ((ParameterizedType) genericInterface).getActualTypeArguments()[0];
block.call(type.newInstance());
} else {
// Code from @danielbodart. AMAZING.
ConstantPool constantPool = (ConstantPool) getConstantPool.invoke(block.getClass());
String[] methodRef = constantPool.getMemberRefInfoAt(20);
int argumentIndex = 0;
String argumentType = jdk.internal.org.objectweb.asm.Type.getArgumentTypes(methodRef[2])[argumentIndex].getClassName();
Class<A> type = (Class<A>) Class.forName(argumentType);
block.call(type.newInstance());
}
}
public static class Thing {
}
public static void main(String[] args) throws Exception {
// Generic arg = class lambdas.TypeTest$Thing
instantitesLambdaArgBasedOnGenericType((Thing message) -> System.out.println(message.getClass()));
// Generic arg = class lambdas.TypeTest$Thing
instantitesLambdaArgBasedOnGenericType((Block<Thing>) (Thing message) -> System.out.println(message.getClass()));
// Generic arg = class lambdas.TypeTest$Thing
instantitesLambdaArgBasedOnGenericType(new Block<Thing>() {
@Override
public void call(Thing message) {
System.out.println(message.getClass());
}
});
}
}
@danieldietrich
Copy link

@tomekl007
Copy link

i've add similar functionality to typesafe-akka library, see my commit :
ktoso/akka@5e14c2d

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment