此C#反射方法的Java等效项是什么

时间:2018-10-04 15:43:20

标签: java reflection interface

我正在将最初用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;
    }
}

1 个答案:

答案 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属性。)