首先我们需要了解函数式接口,从定义上看,使用了关键字interface,也就是说是一个接口,需要有实现。
接口上有@FunctionalInterface注解,作用是限制接口里的方法,限制的具体规则是:函数式接口就是必须有且只能有一个抽象方法的接口(静态方法可以有),在Java中,接口中的方法都隐式添加了public abstract关键字,所以所有方法都是抽象的,我们可以使用@FunctionalInterface注解来规范函数式接口的定义,如果你在接口中添加第二个方法,那么编译器会报错,这就是@FunctionalInterface的作用。
lambda表达式天然是函数接口的一个实现,此时就不存在实现的方法名字约束,因为lambda本身就是一个匿名的方法,他很简单地实现了函数接口。如果不使用lambda表达式,就需要重新建立一个类型,去implement函数接口,然后@Override方法,这样类就是固定了。
@FunctionalInterface
public interface FunctionalInterfaceT {
void test();
// 可以有多个静态方法
static void f1(){}
static void f2(){}
// 可以有多个默认方法
default void test2(){}
default int d2(){return 1;}
// 可以定义Object中非本地方法,实际上继承自Object
boolean equals(Object o);
String toString();
}
有了函数式接口,就需要实现,我们通常使用的实现是Lambda表达式,下面举个实例:
// 声明函数式入参方法
public static <T> T exc(Callable<T> callable) {
return exc(callable, defaultHanlder);
}
public List<City> getAllCities() {
// 调用函数式参数方法
RestResponse<List<City>> resp = Rests.exc(() -> {
String url = Rests.toUrl(houseServiceName, "/house/allCities");
ResponseEntity<RestResponse<List<City>>> responseEntity = rest.get(url, new ParameterizedTypeReference<RestResponse<List<City>>>() {
});
return responseEntity.getBody();
});
return resp.getResult();
}
Java中有个Function接口需要我们关注下,这种泛型和函数式结合的形式。
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
/**
* Returns a composed function that first applies the {@code before}
* function to its input, and then applies this function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of input to the {@code before} function, and to the
* composed function
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
* @throws NullPointerException if before is null
*
* @see #andThen(Function)
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* Returns a composed function that first applies this function to
* its input, and then applies the {@code after} function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of output of the {@code after} function, and of the
* composed function
* @param after the function to apply after this function is applied
* @return a composed function that first applies this function and then
* applies the {@code after} function
* @throws NullPointerException if after is null
*
* @see #compose(Function)
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* Returns a function that always returns its input argument.
*
* @param <T> the type of the input and output objects to the function
* @return a function that always returns its input argument
*/
static <T> Function<T, T> identity() {
return t -> t;
}
}