Wytze
Wytze

Reputation: 1565

Java 8 Stream loses type information

I have the following stream to select objects that match a certain criteria:

    protected final Map<String, PropertyMapping> propertyMappings = new LinkedHashMap();

    public List<PropertyMapping> getPropertyMappingsByAnnotation(final Class annotation) {
        return propertyMappings.values()
            .stream()
            .filter(pm -> pm.getAnnotation(annotation) != null)
            .collect(Collectors.toList());
    }

The filter somehow causes the Stream to lose track of the generic type of the stream which causes the collect statement to fail with the following error:

incompatible types: java.lang.Object cannot be converted to java.util.List<PropertyMapping>

If I change the filter to pm -> true for example the stream works again. What causes this behavior and is there a way to avoid this? It probably has something to do with the 'annotation' class that gets passed in. I tried to pass a final modifier to see if that fixes the problem.

This is the signature of the getAnnotation method:

public final <T extends Annotation> T getAnnotation(Class<T> annotationClass)

Upvotes: 5

Views: 2548

Answers (2)

Shadov
Shadov

Reputation: 5592

Hmm, does collect here know what kind of list it needs to produce (ArrayList/LinkedList)? Try something like this:

List<PropertyMapping> result = propertyMappings.values().stream()
  .filter(pm -> pm.getAnnotation(annotation) != null)
  .collect(Collectors.toCollection(LinkedList::new));

If this doesn't work then maybe try adding a wildcard to the Class argument, or even a type.

Upvotes: 0

khelwood
khelwood

Reputation: 59096

The obvious issue I can see is that you are trying to pass a plain Class variable as an argument to a method that expects a Class<T> where <T extends Annotation>. I imagine that the compiler is failing to fully figure that method call out and it's causing the compilation error at the end of the stream chain. If you fix that, your mystery problem might go away.

Something like this:

public <T extends Annotation> List<PropertyMapping> 
    getPropertyMappingsByAnnotation(Class<T> annotation) {

Upvotes: 8

Related Questions