有没有一种方法可以模拟Java中的属性选择器?

时间:2019-05-05 07:28:10

标签: java c# reflection

在C#中,我们可以选择使用属性选择器(例如,在使用LINQ时)指定对象的属性,如下所示:

var usernames = customers.Where(x => x.Age > 20).Select(x => x.Username);

在这里,我们首先选择属性Age进行比较,然后为Username子句指定属性Select(...)

我目前正在尝试使用Java中的lambda表达式来复制此功能,以使我的代码的用户可以指定稍后应将哪个属性用于某些操作。最终结果应类似于以下内容:

public class Builder<T> {

// ...
private Field field;

Builder<T> forField(SomeFunctionalInterface s) {
    this.field = s.evaluate();
    return this;
 }
// ...
}

谢谢您的努力。

3 个答案:

答案 0 :(得分:2)

下面的示例将正确编译:

public void test() {
  from(Customer.class).where(c -> c.getAge() > 20).select(Customer::getUserName);
}

public <T> Builder<T> from(Class<T> cls) {
  return new Builder<>(cls);
}

public class Builder<T> {
  private Class<T> cls;

  public Builder(Class<T> cls) {
    this.cls = cls;
  }

  public Builder<T> where(Predicate<T> predicate) {
    // store predicate
    return this;
  }

  public Builder<T> select(Function<T, Object> field) {
    // store field selector
    return this;
  }
}

public class Customer {
  private String userName;
  private int age;

  public int getAge() {
    return age;
  }

  public String getUserName() {
    return userName;
  }
}

尽管您不能直接访问private字段,但需要使用它们的吸气剂。

答案 1 :(得分:0)

您可以为此使用流API:

customers.stream().filter(customer => customer.getAge() > 20).map(Customer::getUserName).collect(Collectors.toList())

答案 2 :(得分:0)

我是Linq to Objects(Java)的作者。您可以使用lombok和Linq来实现这一点。

val result = Linq.asEnumerable(customers).where(customer -> customer.getAge() > 20).select(customer -> customer.getUserName());

lombok

Linq