1

If I have a method foo(Predicate bar), I can use it next:

foo(new Predicate<MyObject>() {
        public boolean apply(MyObject obj) { 
           return true;
        }
    }
)

But how can I reach the same result using lambda-style expressions:

foo((MyObject obj) -> true); //obvious compile exception

How can I pass generic type with lambda into the method? Or, simply, how can I create anonymous object of class Predicate(or others) using lambda-style without local variables.

2
  • Okay, I removed them. Do you understand it now? Commented Jan 11, 2016 at 18:19
  • Sorry, I have removed it. My problem is that I want use my parameter variable as object of some class, instead of Object instance. Or call it as foo(obj -> obj.isNice()), where isNice is a method of MyObject class. As I got, I can't pass any generic types with java lambdas, but I can't got why. Commented Jan 11, 2016 at 18:34

2 Answers 2

3

Don't use raw types foo(Predicate<? extends MyObject> bar)

Or cast inside lambda foo(obj -> ((MyObject) obj).myMethod())

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

8 Comments

Raw type is used inside some sdk, and I can't modified it. Why should I cast? I understand, that I can do it, but if base syntax provides functionality to create lambda with generic type, why syntactic sugar does not? It means, that if I use instantiation of Predicate class - I have full functionality, and if I use shorthand syntactic sugar, I lose something of it?
In anonymous inner class you provide extra type info by making it generic. It's equivalent to List list = new ArrayList<MyObject>. Even with generic implementation, you will have to cast from Object after each list.get. Compiler can't guarantee that provider of your sdk won't test your predicate with object wich type is not MyObject in with case inner class impl will fail, even though it looks like typesafe. I would think twice before considering sdk wich uses java8 but not generics (retarded) or at least hide it behind the facade.
Type of lambda defined by the receiver. It always generic. Raw is generic with upper bound of Object. E.g. Predicate<?>. Lambda implemented using invoke dynamic and generally more efficient then anon classes. You also could cast lambda expression like so (Predicate<MyObject>) obj -> .... This semantically identical to your anon class. If that's what you call "functionality".
Wake up. All you doing is tricking compiler to think that obj type is MyObject. So it can blow in your face at runtime. You can't dump generics on top of raw types. Period.
I'd like to think that's intentional. It's a part of good language design to make stupid things at least explicit.
|
1

If your target type is a raw type like in your invocation of foo(Predicate bar), you can’t expect lambda expressions to magically generate an appropriate type for you. It works with the anonymous inner class, because that declaration has an explicit type (Predicate<MyObject> {}) which can get passed to Predicate in an unsafe operation. But lambda expressions have no type. They are converted to a target type and in your invocation, the target type is Predicate.

If you want to create a Predicate<MyObject> via lambda expression, you need Predicate<MyObject> as it’s target type:

Predicate<MyObject> p = o -> /* note that o has the type MyObject */true;
foo(p);

or

foo((Predicate<MyObject>)o -> /* here, o has the type MyObject as well*/true);

or

void fooHelper(Predicate<MyObject> p) {
    foo(p);
}
…
fooHelper(o -> /* here, o has again the type MyObject*/true);

Of course, in all these cases, you could also write (MyObject o) -> true, but this explicit declaration of the parameter has no influence on the type of the instance created with this lambda expression.

Note that the second variant has the formal structure of a type cast, but there won’t be a type cast operation at runtime. It’s only there for specifying the target type for the lambda expression (similar to widening casts used to select a particular overload in a method invocation).

2 Comments

As I understand from the answers, I can do it only with casting or with some proxy. Then why does lambda can not be called just with a generic type, as anonymous class does?
What do you mean with “be called just with a generic type”? Somehow, the compiler has to know, which type the lambda expression shall have, and that works with a type cast. Are you worrying about the two braces? How compact can the syntax get? Is (Predicate<MyObject>)o -> … so much worse than (MyObject o) -> …?

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.