СУХОЙ до Java (лямбда-функции?) - PullRequest
2 голосов
/ 27 марта 2011

Я пишу программу на Java, которая, по сути, тестирует кучу вещей ...

Для каждого вызова мне нужно проверять NullPointerExceptions, StackOverflow, IndexOutOfBounds и т. Д...

Теперь у меня есть повторяющийся шаблон в каждом из моих методов:

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

Поскольку я могу вызывать doSomething() (с разными параметрами) несколько раз в одном методе, я могуthrow

Я бы хотел написать лямбда-тестер, в который я могу передать функцию, но я могуне могу найти способ сделать это с 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 ]

4 голосов
/ 27 марта 2011

Лучшее, что вы можете сделать в 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 для имитации лямбда-выражений - обычное явление в Java. Я даже слышал, как они назывались "SAMbdas".

РЕДАКТИРОВАТЬ: Мое решение не обязательно включает в себя изменение существующих классов:

DoSomething foo = new DoSomething<String>() {
     public String doSomething() { return "Hello World"; }
};
test(foo, "Hello World");
2 голосов
/ 27 марта 2011

Лямбды, к сожалению, еще нет в 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
      }
    }
1 голос
/ 27 марта 2011

Лямбды собираются пробиться в 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
  }
}

Гас Босман прав, хотя. Фреймворк для юнит-тестирования, такой как JUnit, вероятно, очень поможет.

1 голос
/ 27 марта 2011

Это может пойти так:

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


test(new Method<Result1>() {
         public Result1 run() { .... }
     }, expectedResult);
0 голосов
/ 27 марта 2011

Если вы хотите написать это самостоятельно, а не 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
}
...