2014-05-07 42 views
2

我有大量的方法需要应用于给定arrayList的每个成员。问题是,我在编译时不确定哪些方法需要应用于arrayList,并且每次(使用检查)应用它们都将花费巨大(实时应用程序)。所以我现在正在寻找一种方法来给这个列表提供一些方法(一个函数编程)并让它们运行。我知道我可以创建特殊的类,其中每个类只使用一个方法在其每个成员上使用,但大约有50个方法,因此可以快速升级到50个不同的类。这会给项目增加许多不必要的复杂性。有另一种方法吗?对数组列表的每个元素的java运行方法

所以,我正在寻找的是这样的:

public void runMethode(Function f,ArrayList<ObjectWithF> al){ 
    for(ObjectWithF o:al){ 
     o.f(); 
    } 
} 

难道这样的事情在Java中存在吗?或者我将不得不调用所有50种方法或创建50个不同的类?或者包装模式在这里工作?

回答

3

在Java 8中,此功能通过Stream#forEach(Consumer)方法以非常方便的形式提供。

如果您还没有Java 8,那么您可以创建一个接口,并创建实现此接口的匿名类的实例。这有点冗长,但仍比50个已命名的类更好。

设计此接口的方式在结构上等于Java 8中使用的Consumer接口,因此在更新后可以简单地更改为使用Java 8版本可能会有所帮助。

此示例显示了这两种方法的比较:

import java.util.ArrayList; 
import java.util.List; 

class Person 
{ 
    void sayHello() 
    { 
     System.out.println("Hello from "+this); 
    } 
    void sayGoodbye() 
    { 
     System.out.println("Goodbye from "+this); 
    } 

} 

// This interface already exists as java.util.function.Consumer in Java 8 
interface Consumer<T> 
{ 
    void accept(T t); 
} 

public class ForEachTest 
{ 
    public static void main(String[] args) 
    { 
     List<Person> persons = new ArrayList<Person>(); 
     for (int i=0; i<5; i++) 
     { 
      persons.add(new Person()); 
     } 

     runJava8(persons); 
     runJava7(persons); 
    } 

    private static void runJava8(List<Person> persons) 
    { 
     persons.stream().forEach(Person::sayHello); 
     persons.stream().forEach(Person::sayGoodbye); 
    } 

    private static void runJava7(List<Person> persons) 
    { 
     runMethodJava7(persons, new Consumer<Person>() 
     { 
      @Override 
      public void accept(Person person) 
      { 
       person.sayHello(); 
      } 
     }); 
     runMethodJava7(persons, new Consumer<Person>() 
     { 
      @Override 
      public void accept(Person person) 
      { 
       person.sayGoodbye(); 
      } 
     }); 
    } 


    public static void runMethodJava7(
     List<Person> persons, Consumer<? super Person> consumer) 
    { 
     for(Person person : persons) 
     { 
      consumer.accept(person); 
     } 
    }  
} 
1

从Java 8中,使用可以使用Consumer类:

public void runMethod(Consumer<ObjectWithF> consumer, ArrayList<ObjectWithF> al) { 
    for (ObjectWithF o : al) { 
     consumer.accept(o); 
    } 
} 

... 

// for example 
runMethod (o -> System.out.println (o), listOfObjectsWithF); 

// or 
runMethod (System.out::println, listOfObjectsWithF); 

// or even 
listOfObjectsWithF.forEach(System.out::println); 

如果不是Java8,你可以自己创建这个interface并实现它的每一个方法:

interface Consumer { 
    public void apply(ObjectWithF o); 
} 

public void runMethod(Consumer consumer, ArrayList<ObjectWithF> al) { 
    for (ObjectWithF o : al) { 
     consumer.apply(o); 
    } 
} 

... 

runMethod(new Consumer() { 
    public void apply(ObjectWithF o) { 
     //for example 
     System.out.println (o.toString()); 
    } 
}, listOfObjectsWithF); 
1

反映能帮助。

看到代码打击: String obj =“abc”;

String methodName = "toString"; 

    try { 
     Method method = obj.getClass().getMethod("toString"); 
     System.out.println(method.invoke(obj)); 
    } catch (NoSuchMethodException e) { 
     e.printStackTrace(); 
    } catch (SecurityException e) { 
     e.printStackTrace(); 
    } catch (IllegalAccessException e) { 
     e.printStackTrace(); 
    } catch (IllegalArgumentException e) { 
     e.printStackTrace(); 
    } catch (InvocationTargetException e) { 
     e.printStackTrace(); 
    } 

我们有一个obj,并给出了一个方法,我们可以在该对象上运行这个方法。

而且,您还可以考虑定义一个接口,并且列表中的所有对象都实现该接口。并迭代列表,调用界面中定义的那些方法。

+0

这是reflection'的'使用绝对不当的例子,你不会得到任何运行时检查,这是真的,真的很糟糕的设计 –

+0

我同意这种反思的使用是可疑的,至少可以说。在某种程度上,它可能*取决于应该如何确定函数。但最有可能的是,在这里使用自己的界面的方法更合适。 – Marco13

相关问题