我正在将最初用C#完成的框架重写为Java,这让我很困惑。这是一种使用反射来返回使用LINQ实现特定接口的类中的任何属性的方法:
public List<TInterface> GetElementsOfType<TInterface>()
{
return GetType().GetProperties()
.Where(x => typeof(TInterface).IsAssignableFrom(x.PropertyType))
.Select(x => x.GetValue(this, null)).OfType<TInterface>()
.ToList();
}
我正在尝试用Java重新创建,到目前为止已经有了。不太确定是否正确吗?:
public <T> List<?> GetElementsOfType(Class<T> klazz) {
Class<?> props = this.getClass();
List<T> elementsOfType = new ArrayList<>();
try {
Field fieldlist[] = props.getDeclaredFields();
for (Field aFieldlist : fieldlist) {
if (aFieldlist.getType().isAssignableFrom(klazz)){
elementsOfType.add((T)aFieldlist);
}
}
} catch (Exception e) {
return null;
}
return elementsOfType;
}
更新:谢谢大家的帮助。尽管未经检查的强制转换会导致我不得不取消警告,但这似乎对我有用:
@SuppressWarnings("unchecked")
public <T> List<T> GetElementsOfType(Class<T> klazz) {
Class<?> props = this.getClass();
List<T> elementsOfType = new ArrayList<>();
try {
Field fieldlist[] = props.getDeclaredFields();
for (Field aFieldlist : fieldlist) {
if (klazz.isAssignableFrom(aFieldlist.getType())){
elementsOfType.add((T) aFieldlist.get(this));
}
}
} catch (Exception e) {
return elementsOfType;
}
return elementsOfType;
}
}
答案 0 :(得分:1)
在Java中,属性不是字段。属性定义为公用的非静态读取方法,如果不是只读属性,则定义为公用的非静态写入方法。具有一个或多个此类属性的类的实例称为Java Bean。
您可以使用java.beans包检查属性,从Introspector开始:
try {
BeanInfo beanInfo = Introspector.getBeanInfo(props, Object.class);
for (PropertyDescriptor prop : beanInfo.getPropertyDescriptors()) {
if (klazz.isAssignableFrom(prop.getPropertyType())) {
elementsOfType.add(klazz.cast(prop.getReadMethod().invoke(this)));
}
}
} catch (IntrospectionException | ReflectiveOperationException e) {
throw new RuntimeException(e);
}
由于Java使用已检查的异常,因此在这种情况下,您无法轻松地使用Streams编写类似LINQ的代码。可能,但是笨拙。考虑到上面的代码相当简洁,也不值得打扰。
(在Introspector.getBeanInfo(klazz, Object.class)
中使用Object.class的原因是我们不需要Object的属性,即Object.getClass()定义的Object的只读class
属性。)