获取lambdas类的列表 [英] Get a list of classes lambdas
问题描述
在Java 8中,看起来类的lambda保存在数组中。例如,假设我们有这个类:
In Java 8 it looks like the lambdas of a class are kept in an array. For example, lets say we have this class:
public class LambdaFactory {
public Supplier<Integer> getOne(){
return () -> 42;
}
public Supplier<Integer> getTwo(){
return () -> 128;
}
public Supplier<Integer> getThree(){
return () -> 3;
}
}
然后我这样打印出来:
System.out.println(factory.getOne());
System.out.println(factory.getOne());
System.out.println(factory.getTwo());
System.out.println(factory.getThree());
输出类似于
examples.LambdaFactory$$Lambda$1@4e515669
examples.LambdaFactory$$Lambda$1@4e515669
examples.LambdaFactory$$Lambda$2@1b9e1916
examples.LambdaFactory$$Lambda$3@ba8a1dc
所以我们在这里可以看到两件事。调用两次的同一个lambda给了我们相同的lambda对象(这与我们每次都可以得到一个新的内部类不同)。我们也看到他们看起来像是被保留在某种Lambda结构中,而这种结构是该类的一部分
So we can see two thing here. The same lambda called twice gives us the same lambda object (this is not the same as with anon inner classes where we could get a new one every time). We also see that they look like they are being kept in some kind of "Lambda" structure that is part of the class
我的问题是,我可以得到它吗?班里的羔羊?我没有任何理由这样做,我只是喜欢解剖一切
My question is, can I get ahold of the lambdas in a class? I don't have any reason to do so, I just like dissecting things
推荐答案
lambdas是由JRE创建的它们的创建方式由JRE控制,可能因JRE供应商而异,并且可能会在未来版本中发生变化。
The lambdas are created by the JRE and the way they are created is controlled by the JRE and might vary between different JRE vendors and might change in future versions.
如果你想获得乐趣,你可以创建一个lambda运行时在类文件中没有相应的信息:
If you want to have fun you can create a lambda at runtime which has no corresponding information within the class file:
import java.lang.invoke.*;
public class ManualLambda {
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup me=MethodHandles.lookup();
MethodType t=MethodType.methodType(void.class);
MethodType rt=MethodType.methodType(Runnable.class);
CallSite site = LambdaMetafactory.metafactory(
me, "run", rt, t, me.findStatic(ManualLambda.class, "sayHello", t), t);
MethodHandle factory=site.getTarget();
Runnable r=(Runnable)factory.invoke();
System.out.println("created lambda: "+r);
r.run();
}
private static void sayHello() {
System.out.println("hello world");
}
}
上面的代码回顾了创建lambda时会发生什么。但对于编译时(实际)lambda表达式,整个事情由单个 invokedynamic
字节代码指令触发。 LambdaMetafactory.metafactory(...)
方法是 bootstrap 方法,当 invokedynamic
指令第一次执行。返回的 CallSite
对象与 invokedynamic
指令永久关联。如果 CallSite
是 ConstantCallSite
并且其 MethodHandle
返回每次执行时都有相同的lambda对象, invokedynamic
指令将永远生成相同的lambda实例。
The code above retraces what happens when a lambda is created. But for compile-time ("real") lambda expressions the entire thing is triggered by a single invokedynamic
byte code instruction. The LambdaMetafactory.metafactory(…)
method is the bootstrap method which is called when the invokedynamic
instruction is executed the first time. The returned CallSite
object is permanently associated with the invokedynamic
instruction. If the CallSite
is a ConstantCallSite
and its MethodHandle
returns the same lambda object on every execution, the invokedynamic
instruction will "produce" the same lambda instance forever.
这篇关于获取lambdas类的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!