mat_boy mat_boy - 3 months ago 8
Java Question

IntelliJ sees Object in a stream instead of proper class type

I have troubles with reflection, Java8 streams and IntelliJ.

Optional<Class> optionalAnnotationClass=...; // some initialization here
Map<Object, Object> anotherMap=new Hashmap();
Class sourceClass = MyClass.class;// some class

Arrays.asList(sourceClass.getDeclaredFields()).stream()
.filter(field -> (!optionalAnnotationClass.isPresent() || Objects.nonNull(field.getAnnotation(optionalAnnotationClass.get()))))
.filter(field -> filterFieldClass.length == 0 || Arrays.asList(filterFieldClass).contains(field.getType()))
.map(field -> doSomething(sourceClass, field))
.filter(Objects::nonNull)
.forEach(entry -> anotherMap.put(entry.getKey(), entry.getValue()));


But IntelliJ15 annoys me with the following messages

enter image description here

It starts complaining that
field
is an
Object
and not a
Field
starting after the first
filter
, so at line

.filter(field -> filterFieldClass.length == 0 || Arrays.asList(filterFieldClass).contains(field.getType()))


I checked the version of the project, it is with target 1.8 and uses JDK8. I invalidated the cache and restarted IntelliJ.

What's wrong?




Here is the full code, for completeness

package com.ladop;

import com.google.common.base.CaseFormat;
import com.google.common.collect.Maps;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static com.google.common.base.Preconditions.checkArgument;

public class StaticReflectionUtils {

public static Map<String, Object> extractStaticField(final Class<?> sourceClass,
final Optional<Class> optionalAnnotationClass,
final Class<?>... filterFieldClass) {
final Map<String, Object> fieldNameToValue = new HashMap<>();
Arrays.stream(sourceClass.getDeclaredFields())
.filter(field -> !optionalAnnotationClass.isPresent() || Objects.nonNull(field.getAnnotation(optionalAnnotationClass.get())))
.filter(field -> filterFieldClass.length == 0 || Arrays.asList(filterFieldClass).contains(field.getType()))
.map(field -> extractFieldKeyValue(sourceClass, field))
.filter(Objects::nonNull)
.forEach(entry -> fieldNameToValue.put(entry.getKey(), entry.getValue()));
return fieldNameToValue;
}

public static Map.Entry<String, Object> extractFieldKeyValue(final Class<?> sourceClass,
final Field field) {
field.setAccessible(true);
try {
final String fieldName = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, field.getName());
return Maps.immutableEntry(
concatenate(sourceClass.getSimpleName(), fieldName), field.get(null));
} catch (IllegalAccessException e) {
}
return null;
}

protected static String concatenate(final String prefix, final String word) {
return new StringBuilder()
.append(prefix)
.append("_")
.append(word).toString();
}

}

Answer

First, change Hashmap() to HashMap<>(), and ... to Optional.empty() for compilable code.

Second, your example is missing some declarations to be Minimal, Complete, and Verifiable, so I added this for testing:

private static class MyClass {}
private static Class<?>[] filterFieldClass = {};
private static Map.Entry<Object, Object> doSomething(Class<?> sourceClass, Field field) {
    return null;
}

And all compile errors disappeared! (jdk1.8.0_91)

So, if your code doesn't compile, the three declarations I assumed there are differently typed in your code. Most likely the doSomething() takes or returns different types.


On a side note, your code is using raw types. Don't! Change the following:

  • Optional<Class> to Optional<Class<? extends Annotation>>
  • Class sourceClass to Class<?> sourceClass

Also, Arrays.asList(...).stream() should be Arrays.stream(...).

Comments