digitig
digitig

Reputation: 2130

Passing a Java Predicate around

I'm having trouble using Java Predicates.

I have an enum:

public enum ValidationErrors {
    INCONSISTENT_IS_CITATION_ERROR((SacmElement element)->{
        return !element.getCitedElement().isPresent() || element.getIsCitation();} );

    private final Predicate<? extends SacmElement> isValid;

    ValidationErrors(Predicate<? extends SacmElement> isValid) {
        this.isValid = isValid;
    }

    public Predicate<? extends SacmElement> getIsValid() {
        return isValid;
    }
}

Now within a member of the class SacmElement I try to do the test:

if (ValidationErrors.INCONSISTENT_IS_CITATION_ERROR.getIsValid().test(this))

That doesn't compile because "The method test(capture#1-of ? extends SacmElement) in the type Predicate is not applicable for the arguments (SacmElement).

I don't understand the error: I thought that for the purposes of Java generics a class is considered to extend itself. What am I doing wrong?

Upvotes: 3

Views: 986

Answers (1)

John Kugelman
John Kugelman

Reputation: 361605

A good rule of thumb to remember is PECS: Producer Extends, Consumer Super. A predicate is a consumer, so it should use super. Use Predicate<? super SacmElement> instead of Predicate<? extends SacmElement>.

With super, you could have a predicate that checks SacmElements, or you could have one that's even more generic and checks any old Object. A Predicate<Object> would work here, wouldn't it?

With extends, you may have yourself a predicate that can only handle some specific sub-class of SacmElement rather than all SacmElements. That's no good. What if you're trying to test a regular SacmElement but the predicate only accepts SpecificSacmElements?

Upvotes: 3

Related Questions