干掉java(lambda函数?)

时间:2011-03-27 17:22:53

标签: java lambda dry

我正在用java编写一个基本上测试一堆东西的程序......

对于每次通话,我都需要检查NullPointerExceptionsStackOverflowIndexOutOfBounds等...

我现在每个方法都有这种重复模式:

try {
  doSomething();
} catch(NullPointerExceptions npe) {
  // prints something
} catch(StackOverflow soe) {
  // prints something
} catch(IndexOutOfBounds iob) {
  // prints something
}

由于我可以在一个方法中多次调用doSomething()(使用不同的参数),我不能只将throw异常备份到main(因为我需要实际运行的下一个测试) )。

我想写一个lambda测试器,我可以传递一个函数,但我找不到用java做的方法:(。

我想做点什么:

private void test(Method m, E expectedValue) {
  try {
    if(!m.run().equals(expectedValue))
      System.out.println("FAILED TEST: "+m.name()+". Value was "+m.run()+", should have been "+expectedValue);
  } catch() {
    // see above
  }
}

5 个答案:

答案 0 :(得分:4)

您在Java中可以做的最好的事情就是使用界面:

interface DoSomething<E extends Comparable<E>> {
  E doSomething();
}

然后您的test方法可能如下所示:

private void test(DoSomething<E> m, E expectedValue) {
  try {
    if(!m.doSomething().equals(expectedValue))
      System.out.println("FAILED TEST");
  } catch() {
    //handle exception
  }
}

E需要延长Comparable<E>,因为您在equals内呼叫test

这称为SAM(单一抽象方法)接口。使用SAM类和接口来模拟lambdas是Java中常见的事件。我甚至听说过他们叫做“SAMbdas”。

编辑:我的解决方案不一定涉及修改现有类:

DoSomething foo = new DoSomething<String>() {
     public String doSomething() { return "Hello World"; }
};
test(foo, "Hello World");

答案 1 :(得分:2)

遗憾的是,Lambda尚未出现在java中。但是你可以使用泛型java.util.concurrent.Callable:

private <T> void test(Callable<T> c, T expectedValue) {
      try {
        if(!c.call().equals(expectedValue))
          System.out.println("FAILED TEST: "+c+". Value was "+c.call()+", should have been "+expectedValue);
      } catch(Exception ex) {
        // see above
      }
    }

答案 2 :(得分:1)

可能会这样:

abstract class Method<R> {
     public R run();
}


test(new Method<Result1>() {
         public Result1 run() { .... }
     }, expectedResult);

答案 3 :(得分:1)

Lambdas将继续努力进入JDK7。如果您想尝试一下,请从Oracle

获取一个早期访问版本

http://www.jcp.org/en/jsr/detail?id=335

那就是说,我不太明白这个问题。你能举一个例子说明你打算如何使用这些方法吗?您建议的方法听起来像是在正确的轨道上,尝试:

private void test(Method m, Object target, Object[] args, E expectedValue) {
  try {
    if(!m.invoke(target, args).equals(expectedValue))
      System.out.println("FAILED TEST: "+m.name()+". Value was "+m.run()+", should have been "+expectedValue);
  } catch() {
    // see above
  }
}
不过,Gus Bosman是对的。像JUnit这样的单元测试框架可能会帮助很多。

答案 4 :(得分:0)

如果您想自己编写,而不是JUnit,可以使用Reflection来调用该方法。

所以,不要说m.run(),而是使用java.lang.reflect.Method#invoke

try {
  method.invoke(obj, arg1, arg2,...);
} catch (Exception e) {
  // there are several Reflection exceptions you also need to deal with
}