4

According to JLS 15.27.2 the lambda body has the same scope as the surrounding context and I would like to know if there is a specific reason to why default methods from the interface that is implemented by the lambda aren't available within the body too? Does this restriction enable some optimization or is it just to keep the overload rules simple?

I was prototyping some Java 8 API today and when I hit this limitation I was pretty disappointed because using default methods would have allowed me to implement that API in a very elegant and non-intrusive way.

Achieving the same elegancy is more or less possible by requiring a static import, but that results in "polluting" the namespace.

Is there a chance that this restriction will be lifted?

7
  • a short example would be helpful to understand what you are talking about Commented Apr 14, 2016 at 16:05
  • 1
    Related (though not a duplicate): stackoverflow.com/q/33108540/3973077 Commented Apr 14, 2016 at 16:06
  • 1
    the lambda body has the same scope as the surrounding context” already implies that there are no spurious default methods in scope. Of course, this simplifies the name resolution rules a lot. And it all boils down to the mantra “lambda expressions are not syntactic sugar for inner classes”… See also here Commented Apr 14, 2016 at 16:26
  • The related question actually includes a good example. Commented Apr 14, 2016 at 17:16
  • 1
    Possible duplicate of Can a lambda access members of its target functional interface? Commented Apr 15, 2016 at 1:26

1 Answer 1

5

The default methods aren't available to the lambda, because the lambda has not yet been given a type until it is assigned to a functional type. For example, the lambda

s -> s.isEmpty()

could be assigned to a java.util.function.Predicate or a com.google.common.base.Predicate. For that reason it doesn't have access to java.util.function.Predicate's default methods until it is actually assigned to a java.util.function.Predicate by direct assignment to a java.util.function.Predicate, by passing the lambda as a java.util.function.Predicate parameter, returning it from a function whose return type is java.util.function.Predicate, or simply casting it to a java.util.function.Predicate like this:

((Predicate<String>) s -> s.isEmpty()).negate();   // negate is a default method on Predicate

One way to think of it is being analogous to boxing an int value. Integer's methods can't be called on a literal integer value, but once the integer value is assigned to an Integer type, one can call its methods.

Sign up to request clarification or add additional context in comments.

2 Comments

Well I don't see how that is a reason. I don't know how the compiler is implemented but since the lambda type is inferred from the LHS the compiler should already know the type when it checks the lambda body.
I see your point, and I don't intend to defend the compiler design. My understanding, FWIW, is that a lambda is a body without a signature and a functional interface is a signature without a body, and it isn't until the assignment or cast that the two are joined and an actual function gets generated. Hope that helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.