java7 이하에서는 Callable 메소드를 생성하면 다음과 같은 형식으로 개발했다.
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
...
String text = "1";
Callable<Integer> task = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return Integer.parseInt(text);
}
};
FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
futureTask.run();
try {
System.out.println(futureTask.get());
} catch (Exception e) {
e.printStackTrace();
}
java8에서는 Callable의 call을 람다표현으로 깔끔하게 구성할 수 있다.
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
...
String text = "1";
FutureTask<Integer> futureTask = new FutureTask<Integer>(() -> {
return Integer.parseInt(text);
});
futureTask.run();
try {
System.out.println(futureTask.get());
} catch (Exception e) {
e.printStackTrace();
}
그 이유는 java에서 @FunctionalInterface를 사용하는 코드는 알아서 람다 표현식으로 사용할 수 있게 한다.
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
Runnable도 동일하다.
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
비슷하게 Runable을 테스트해본다.
Runnable runabble = new Runnable() {
@Override
public void run() {
System.out.println("Run!!");
}
};
Thread th = new Thread(runabble);
th.start();
Thread.sleep(1000);
위의 코드와 아래 코드는 동일하다.
Thread th = new Thread(() -> {
System.out.println("Run!!");
});
th.start();
Thread.sleep(1000);
java8의 functional interface는 java language spec(https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.8)에서 정의되어 있고 오직 하나의 abstract method으로 구성된다.
Invalid '@FunctionalInterface' annotation; ... is not a functional interface가 뜬다면 잘못 functional interface를 정의했다는 것을 컴파일에러로 알려준다.
FunctionalInterface를 사용자 정의 선언을 할 수 있다.
@FunctionalInterface
interface BindCallable {
public List<String> bind();
}
class Bind {
public List<String> process(BindCallable callable){
return callable.bind();
}
}
간단한 예시이다.
Bind bind = new Bind();
List<String> result = bind.process(() -> {
final String a = "a";
final String b = "b";
List<String> list = Lists.newArrayList();
list.add(a); list.add(b);
return list;
});
System.out.println(result);