Joao
Joao

Reputation: 131

Java lambda: Expected Object but found MyClass

If I have:

public class MyClass{
    MyClass(Object b){
        //Some code here
    }
}

And I do:

MyClass X = new MyClass(new SomeOtherClass());

It works just fine, im assuming, because every class has Object as a superclass.

But, if I do:

import java.util.function.Predicate;
public class MyClass{
    MyClass(Predicate<Object> b){
        //Some more code here
    }
}

And then:

MyClass X = new MyClass((SomeOtherClass s) -> {
    //Even more code
    return true;
});

I get an error saying:

Incompatible parameter types in lambda expression: expected Object but found SomeOtherClass

Shouldn't I be able to send a SomeOtherClass object in that lambda expression? I'm using the Object class because i wanna be able to recieve not only SomeOtherClass, but also SomeOtherClassXPTO. I tried looking this up and found nothing so far, so my apologies in advance if this has been asked before.

Upvotes: 5

Views: 3934

Answers (3)

Oleksandr Pyrohov
Oleksandr Pyrohov

Reputation: 16216

As you know, the following is valid:

Object o = new SomeOtherClass();

But, this doesn't apply to generics, because generics are not covariant:

Predicate<Object> p;

p = (SomeOtherClass s) -> false; // compiler error - incompatible parameter types...

The only possible assignment to the Predicate<Object> is:

Predicate<Object> p = object -> ... ;

At the same time, the input to this predicate can be of any type:

p.test(new Object());
p.test("");
p.test(99);

As stated in the Yassin's answer, consider Predicate<? extends Type> in order to gain flexibility.

Upvotes: 1

azro
azro

Reputation: 54148

Inheritance does not work for Generic parameter, the official doc about can be found here


You need to

MyClass(Predicate<? extends Object> b) {
    //Some more code here
}

or

MyClass(Predicate<?> b) {
    //Some more code here
}

Upvotes: 1

Yassin Hajaj
Yassin Hajaj

Reputation: 21975

Well, when you defined your predicate as Predicate<Object> it's restricted to only accept objects which getClass() method returns Object.

For this method to work you would be doing something like Predicate<? extends Object> but this does not make much sense. Use Predicate<?> alone then.

Otherwise, another way to solve this is to find the common denominator of your two classes, probably a parent class and use Predicate<? extends ParentClass>.

A final solution would be to create, depending on your application logic, an interface and implementing the interface by both objects to be able to something like the following Predicate<? extends YourInterface>

Upvotes: 3

Related Questions