java lambda例子,通过名称实例化Java lambda函数

I would like to create a lambda function in Java 8, get it's classname and then later instantiate the function again from its classname.

This is what I try:

import java.util.function.Consumer;

public class SimpleLambda

{

public static void call(String aLambdaClassName, String aArg) throws Exception

{

Class> lClass = (Class>) Class.forName(aLambdaClassName);

Consumer newlamba = lClass.newInstance();

newlamba.accept(aArg);

}

public static void main(String[] args) throws Exception

{

{

// Attempt with a static method as lambda

Consumer lambda = Host::action;

String classname = lambda.getClass().getName();

call(classname, "Hello world");

}

{

// Attempt with a locally defined lambda

Consumer lambda = (s) -> { System.out.println(s); };

String classname = lambda.getClass().getName();

call(classname, "Hello world");

}

}

}

class Host {

public static void action(String aMessage) {

System.out.println(aMessage);

}

}

However, with this code (in both variants, using the static method reference and using the locally declared lambda), I get an exception:

Exception in thread "main" java.lang.ClassNotFoundException: mypackage.SimpleLambda$$Lambda$1/471910020

at java.lang.Class.forName0(Native Method)

at java.lang.Class.forName(Class.java:264)

at mypackage.SimpleLambda.main(SimpleLambda.java:12)

I would have expected that at I can at least re-instantiate the static method reference... nope, apparently not.

I have been using a similar approach with Groovy Closures and that worked nicely. So am I just doing something wrong with the Java 8 lambdas, or is it not possible to instantiate lambdas by name? I found some hints on the net that lambdas can be (de)serialized, so I would expect it should also be possible to instantiate them by name.

解决方案

Well, it is a special property of Oracle’s JRE/OpenJDK to use “anonymous classes”, which can’t be accessed by name at all. But even without this, there is no reason why this ought to work:

Class.forName(String) tries to resolve the class via the caller’s ClassLoader. So even if lambda expressions were implemented using ordinary classes, there were not accessible if loaded via a different ClassLoader

Class.newInstance() only works if there is a public no-arg constructor. You can’t assume that there is a no-arg constructor nor that it is public

The assumption that the entire function’s logic has to reside in a single class is wrong. A counter-example would be java.lang.reflect.Proxy which generates interface implementations delegating to an InvocationHandler. Trying to re-instantiate such a proxy via its class name would fail, because you need the to pass the actual InvocationHandler instance to the proxy’s constructor. In principle, the JRE specific lambda expression implementation could use a similar pattern

Considering the points above, it should be clear that you can’t say that it worked with inner classes in general. There are a lot of constraints you have to fulfill for that.

Regarding Serialization, it works for serializable lambda expressions, because the persistent form is completely detached from the runtime implementation class, as described in this answer. So the name of the generated class is not contained in the serialized form and the deserializing end could have an entirely different runtime implementation.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值