【问题标题】:How to call method from parameter JAVA如何从参数JAVA调用方法
【发布时间】:2016-03-08 10:23:33
【问题描述】:

我的问题是重复代码。我有 4 种方法,如下所示,一种用于名称,另一种用于登录等。所以唯一改变的是 getter(p.getName()、p.getLogin()...)。

private Set<Person> filterByName(Set<String> values, Set<Person> peeps){
    Set<Person> filtered = new HashSet<>();
    for (Person p : peeps){
        if(isIn(p.getName(), values)){
            filtered.add(p);
        }
    }
    return filtered;
}

我在 switch 中调用这些方法:

switch(var){
     case NAME:
          filtered = filterByName(arg1, arg2);
     case ...

如果不为每个 case 块实现方法,我该如何做到这一点?

我的想法是以某种方式告诉方法在case 块中使用正确的getter,因此只有一种方法用于所有过滤,例如

private Set<Person> universalFilter(Set<String> values, Set<Person> peeps) {
Set<Person> filtered = new HashSet<>();
    for (Person p : peeps){
        if(isIn(***SOMETHING CLEVER***, values)){
            filtered.add(p);
        }
    }
    return filtered;
}

【问题讨论】:

  • Java 的哪个版本?如果 8,这听起来像是 Predicate 的工作......或者如果小于 8,那么 Guava 也有 Predicate。

标签: java methods call


【解决方案1】:

一种简单的方法是使用 switch 变量作为参数传递给 Person 上的新方法 get()。

if(isIn(p.get(var), values)){

然后在Person中实现新方法,例如:

public void get(String var) {
  if (var.equals("NAME")) return name;
  ...
}

【讨论】:

    【解决方案2】:

    您可以传递另一个字符串参数,这将是您想要过滤的变量(“名称”、“登录”...)

    然后通过反射,您可以找到并调用相关的 getter 方法:

    Method method = Person.class.getMethod("get"+ filter, null);
    
    String returnValue = (String)(method.invoke(p, null));
    
    if(isIn(returnValue , values))
    ...
    

    【讨论】:

    • 我认为你的意思是“反射”,而不是“递归”
    • 我将第一行修改为: Method method = Person.class.getMethod("get"+ filter, null);它有效。谢谢,这就是我想要的:)
    • @arcy ,是的,我刚刚更正了,谢谢指点!
    【解决方案3】:

    如果您使用的是 Java 8,则可以使用方法引用来做您想做的事。最小的变化是使用Function 对象。您的 filterByName 方法需要一个附加参数,该参数将每个 Person 对象映射到您要测试的属性:

    private Set<Person> filter(Function<Person,String> filter, Set<String> values, Set<Person> peeps) {
        Set<Person> filtered = new HashSet<>();
        for (Person p : peeps){
            if(isIn(filter.apply(p), values)){
                filtered.add(p);
            }
        }
        return filtered;
    }
    

    然后你调用方法如下:

    filter(Person::getName, values, peeps);
    

    如果要允许更复杂的过滤器,可以将整个过滤器指定为谓词:

    private Set<Person> filter(Predicate<Person,String> filter, Set<Person> peeps) {
        Set<Person> filtered = new HashSet<>();
        for (Person p : peeps){
            if (filter.test(p)){
                filtered.add(p);
            }
        }
        return filtered;
    }
    

    可以调用:

    filter(p -> isIn(p.getName(), values), peeps); 
    

    事实上,Java 8 在运行时库中提供了过滤功能,或者通过removeIf 方法:

    private Set<Person> filter(Predicate<Person,String> filter, Set<Person> peeps) {
        Set<Person> filtered = new HashSet<>();
        filtered.removeIf(filter);
        return filtered;
    }
    

    或使用流:

    private Set<Person> filter(Predicate<Person,String> filter, Set<Person> peeps) {
        return peeps.stream().filter(filter).collect(Collectors.toSet());
    }
    

    【讨论】:

      猜你喜欢
      • 2018-10-14
      • 1970-01-01
      • 2019-05-01
      • 2012-11-08
      • 1970-01-01
      • 2018-07-30
      • 2012-07-04
      • 1970-01-01
      • 2022-01-17
      相关资源
      最近更新 更多