Parsing and Translating Java 8 lambda expressions

2019-01-18 04:22发布

问题:

In C# you can enclose a lambda expression in an expression tree object and then possibly parse it. I was wondering if this is also possible in Java?

What I'm looking for is doing something like this:

BooksRepository.getAll()
.where(b -> b.getIban() == "SomeIban")
.and(b -> b.getAuthor() == "SomeAuthor"); //etc.

And then the BooksRepository should somehow translate that query to the following RESTful API request based on the predicates specified as lambdas:

GET http://mylibrary.com/books?Iban=SomeIban&Author=SomeAuthor

and then return the result to the client. Any idea if this is even possible in Java?

回答1:

Yes, it's possible. I made a library that does exactly that: JaQue



回答2:

I'm the author of Jinq. The automatic conversions of lambdas into expression trees that can be read at runtime is a C# only feature. That feature doesn't really have any general-purpose use for normal programmers. It's basically only useful for implementing LINQ, so language designers haven't been keen on adding that feature to Java or other languages. There has been talk of adding some sort of compiler plugin framework for Java that would allow you to add the expression tree feature to Java yourself, but I'm not too familiar with progress on that project.

Jinq contains a bytecode analysis framework that can build simple expression trees from the bytecode of a lambda at runtime. It is based on symbolic execution and ASM. It can be used to convert lambdas into expression trees, just like C#, but it's pretty heavy weight procedure with a lot of hoops to jump through, so it might be overkill for what you want to do. You'd be swatting a fly with a hammer, essentially.

There are languages other than Java that run on the JVM that have better support for the metaprogramming that you want to do. So you might also want to consider looking at Groovy or Scala for that.



回答3:

Something like Jinq?

database.customerStream().where(customer -> customer.getName().equals("Alice"));


回答4:

I explain my approach here http://benjiweber.co.uk/blog/2013/12/28/typesafe-database-interaction-with-java-8/

Basically, replay the lambda against a fake object that records the interactions at runtime.