IntelliJ在流中看到Object而不是正确的类类型

时间:2016-08-27 17:36:43

标签: java intellij-idea java-8 java-stream

我在使用反射,Java8流和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()));

但是IntelliJ15使用以下消息来惹恼我

enter image description here

它开始抱怨fieldObject而不是Field从第一个filter开始,所以在行

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

我检查了项目的版本,它是使用目标1.8并使用JDK8。我使缓存失效并重新启动IntelliJ。

出了什么问题?

以下是完整代码的完整代码

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();
    }

}

2 个答案:

答案 0 :(得分:4)

首先,将Hashmap()更改为HashMap<>(),将...更改为Optional.empty()以获取可编辑的代码。

其次,您的示例缺少一些声明为Minimal, Complete, and Verifiable,因此我将其添加到测试中:

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

所有编译错误都消失了! (jdk1.8.0_91)

因此,如果您的代码没有编译,我假设的三个声明在您的代码中有不同的类型。很可能doSomething()接受或返回不同的类型。

更新: Eclipse编译好了。使用javac 1.8.0_91进行编译会产生错误,通过修复原始类型可以消除这些错误,如下所述 我猜Eclipse编译器在推断lambdas时比在Oracle编译器中更好(?)

另外,您的代码使用的是原始类型。 不要!更改以下内容:

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

此外,Arrays.asList(...).stream()应为Arrays.stream(...)

答案 1 :(得分:0)

由于这个原因,我不明白,JDK不喜欢第一个过滤器。我通过将表达式包装到方法中来改变它。 从:

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()));

Arrays.asList(sourceClass.getDeclaredFields()).stream()
            .filter(field -> hasAnnotationIfPresent(field, optionalAnnotationClass))
            .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()));

使用定义为:

的方法
private static boolean hasAnnotationIfPresent(final Field field, final Optional<Class> optionalAnnotationClass) {
    return !optionalAnnotationClass.isPresent() || Objects.nonNull(field.getAnnotation(optionalAnnotationClass.get()));
}