我在使用反射,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使用以下消息来惹恼我
它开始抱怨field
是Object
而不是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();
}
}
答案 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 sourceClass
至Class<?> 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()));
}