Ist es möglich, den Lambda-Ausdruck zur Laufzeit abzurufen?
Ich habe letzte Nacht mit Java8 Lambda gespielt und mich gefragt, ob es möglich ist, den Lambda-Ausdruck zur Laufzeit abzurufen. Kurz und so weit ich weiß, werden Lambda-Ausdrücke zur Laufzeit in (statische) Methoden konvertiert und dann mit InvokeDynamics aufgerufen.
Nehmen wir ein Beispiel wie dieses:
people.filter(person -> person.getAge() >= minAge);
woherfilter
wäre eine benutzerdefinierte Methode unter aPredicate<T>
als Parameter. In diesemfilter
Methode, wie könnte ich das Argument in einer Form ähnlich (oder identisch) zum Lambda-Ausdruck abrufen (person -> person.getAge() >= minAge
) in diesem Fall ?
Ich habe versucht, den generierten Bytecode der Klasse des Arguments mit ASM5_BETA zu lesen, aber ich konnte nicht weiter gehen als mit einem ClassVisitor und einem MethodVisitor zu der Methode zu gelangen, die dem Lambda-Ausdruck zugeordnet ist.
public <T> List<T> filter(Filter<T> expression) {
try {
Class<? extends Filter> expressionClass = expression.getClass();
byte[] content = getClassContent(expressionClass);
ClassReader classReader = new ClassReader(content);
classReader.accept(new PredicateClassVisitor(), 0);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
private byte[] getClassContent(Class<? extends Filter> expressionClazz) throws
IOException {
InputStream stream = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(getClassName(expressionClazz.getName()));
return IOUtils.toByteArray(stream);
}
private String getClassName(String expressionClazz) {
return expressionClazz.substring(0, expressionClazz.indexOf('Ich bin mir nicht sicher, ob dies der richtige Weg ist, und ich habe mich gefragt, ob ASM oder JDK8 für einen solchen Zweck besser geeignet sind.
Danke für jeden Rat ;-) Viele Grüße, Xavier
))
.replace('.', '/') + ".class";
}
static class PredicateClassVisitor extends ClassVisitor {
public PredicateClassVisitor() {
super(Opcodes.ASM4);
}
@Override
public MethodVisitor visitMethod(int i, String s, String s2, String s3,
String[] strings) {
return new PredicateMethodVisitor();
}
}
static class PredicateMethodVisitor extends MethodVisitor {
public PredicateMethodVisitor() {
super(Opcodes.ASM4);
}
@Override
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
Object... bsmArgs) {
for (Object object : bsmArgs) {
System.out.println(" " + object.toString());
}
}
}
Ich bin mir nicht sicher, ob dies der richtige Weg ist, und ich habe mich gefragt, ob ASM oder JDK8 für einen solchen Zweck besser geeignet sind.
Danke für jeden Rat ;-) Viele Grüße, Xavier