我很难把这个方法改写成更易读、更容易理解的东西。
static Stream<Class<? extends MyType>> collectMyTypes(Object o) {
return Reflection.lineage(o.getClass())
.flatMap(c -> Arrays.stream(c.getDeclaredFields()))
.map(Field::getGenericType)
.filter(t -> t instanceof ParameterizedType)
.map(t -> (ParameterizedType) t)
.filter(t -> t.getRawType() == MyTypeWrapper.class)
.map(t -> t.getActualTypeArguments()[0]) //MyTypeWrapper is final and has only 1 type argument.
.filter(t -> t instanceof Class)
.map(t -> (Class<? extends MyType>) t);
}下面是我使用的工具/类:
Reflection.lineage(Class<T>)遍历T的所有父类;MyTypeWrapper定义为final class MyTypeWrapper<T extends MyType>;MyType被定义为abstract class MyType。这段代码让我感到烦恼的是,它很难读懂,主要是因为在实例上有一系列的过滤器,然后映射。我试图在Java 8中找到类似于番石榴的Iterables.filter(Iterable,Class)的东西,但是还没有找到任何类似的方法(虽然我实现了类似的方法,但是代码看起来像Lisp)。另外,打给Arrays.stream的电话也让我感到不安。是的,我可以把它分成.map(Class::getDeclaredFields).flatten(Arrays::stream),但是这会增加一些不必要的复杂性,不是吗?
无论如何,任何意见都是欢迎的。
给定下面的示例,此方法将保留/跳过各种字段。
class GoodExample extends MyType {}
class BadExample extends MyType {}
class Example {
// GoodExample will be returned.
MyTypeWrapper<GoodExample> object1;
// BadExample will be skipped because the type is a wildcard
MyTypeWrapper<? extends BadExample> object2;
// There is no type to return so this field is skipped.
MyTypeWrapper object3;
// This is not an instance of MyTypeWrapper so it's skipped.
Object object4;
// This is generic, but still not a MyTypeWrapper, so it's skipped.
List<BadExample> object5;
}编辑:
最初的方法是:
List<Class<? extends MyType>> types = new ArrayList<>();
Reflection.lineage(o.getClass())
.forEach((c) -> {
for (Field f: c.getDeclaredFields()) {
Type type = f.getGenericType();
if (!(type instanceof ParameterizedType)) {
continue;
}
ParameterizedType pType = (ParameterizedType)type;
if (pType.getRawType() != MyTypeWrapper.class) {
continue;
}
// length is 1.
Type argType = pType.getActualTypeArguments()[0];
if (!(argType instanceof Class)) {
continue;
}
Class<? extends MyType> argClass = (Class<? extends MyType>)argType;
types.add(argClass);
}
});
return types;发布于 2015-08-04 01:14:12
我可以建议的是将后续的filter()/map()步骤放入某种提取方法中:
@SuppressWarnings("rawtypes")
private static Optional<Type> extractMyType(Field field) {
return Optional.of(field.getGenericType())...;
}您还可以将filter()/map()步骤作为一个方法:
private static <T, R> Optional<R> filterAndMap(T obj, Predicate<? super T> filter,
Function<? super T, ? extends R> mapper) {
return Optional.of(obj).filter(filter).map(mapper);
}为了方便起见,您可以创建一个cast()方法,该方法调用filterAndMap()来处理安全转换:
private static <T, R> Optional<R> cast(T obj, Class<R> clazz) {
return filterAndMap(obj, clazz::isInstance, v -> (R) obj);
}然后,extractMyType()的核心实际上变成了三个flatMap()操作:
@SuppressWarnings("rawtypes")
private static Optional<Class> extractMyType(Field field) {
return Optional.of(field.getGenericType())
.flatMap(v -> cast(v, ParameterizedType.class))
.flatMap(v -> filterAndMap(v,
v1 -> v1.getRawType() == MyTypeWrapper.class,
v1 -> v1.getActualTypeArguments()[0]))
.flatMap(v -> cast(v, Class.class));
}最后,collectMyTypes()方法只对结果的Optional包装器实例执行一个简单的筛选:
@SuppressWarnings("unchecked")
static Stream<Class<? extends MyType>> collectMyTypes(Object o) {
return Reflection.lineage(o.getClass())
.flatMap(c -> Arrays.stream(c.getDeclaredFields()))
.map(YourClass::extractMyType).filter(Optional::isPresent)
.map(Optional::get);
}https://codereview.stackexchange.com/questions/98952
复制相似问题