【问题标题】:What's the Java equivalent of this C# reflection method这个 C# 反射方法的 Java 等价物是什么
【发布时间】:2019-03-10 01:59:21
【问题描述】:

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

【问题讨论】:

  • 如果您使用的是 java 8,您可以查看 java 8 流,它几乎可以和上面的 C# 版本做同样的事情
  • 是的,使用 Java 8,没有研究流
  • 您希望参数到isAssignableFrom 的顺序与 C# 中的顺序相同

标签: java reflection interface


【解决方案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属性。)

【讨论】:

  • 不幸的是,这每次都会抛出 IntrospectionException。有任何想法吗?我这样称呼它: List editableElements = bingHomePage.GetElementsOfType(Editable.class);
  • IntrospectionException 的消息是什么?它的堆栈跟踪是否包含任何“由”部分?
  • 我认为它可能与这个stackoverflow.com/questions/4438815/…有关
  • 该错误似乎与在继承层次结构中的不同类中具有 get-methods 和 set-methods 有关。你的道具课是这样吗?如果不是,则异常更有可能实际上是在告诉您问题所在。
  • 谢谢,是的,我在读取堆栈跟踪 atm 时遇到问题(使用 VS 代码,似乎存在一些问题),但这听起来很正确。好消息我现在已经使用我的初始代码让它工作了(见更新),但会尝试重构它以让你的方法工作
猜你喜欢
  • 2011-03-19
  • 1970-01-01
  • 1970-01-01
  • 2013-10-15
  • 1970-01-01
  • 2013-05-17
  • 2018-11-30
  • 2011-10-13
  • 1970-01-01
相关资源
最近更新 更多