函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。
如定义了一个函数式接口,使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的)如下:
@FunctionalInterface
public interface CustomInterface<T> {
T get();
}
class Demo{
public static void main(String[] args) {
String[] arr = {"hello","world"};
//Arrays.asList(arr) 默认返回类型为ArrayList
CustomInterface<List<String>> ci = ()-> Arrays.asList(arr);
List<String> list = ci.get();
}
}
jdk1.8中新加入很多函数式接口,以供函数式编程使用,下面介绍一下:
- Supplier 结果提供者,具有生成一个结果的能力,举个栗子:
@Slf4j
public class Demostration<T> {
public static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static <BuildList> void main(String[] args) {
//栗子1:返回一个当前日期时间
Supplier<LocalDateTime> localDate = LocalDateTime::now;
LocalDateTime dateTime = localDate.get();
log.info("now:{}",dateTime);
//返回格式化时间
Supplier<String> dateTimeFormat = ()->dateTime.format(dateTimeFormatter);
log.info("date:{}",dateTimeFormat.get());
//返回数组
String[] arr = new String[]{"hello","world","every","body!"};
Supplier<List<String>> s = () -> Arrays.asList(arr);
List<String> list1 = s.get();
log.info("list:{}",list1);
//栗子2:返回一个supplier
Demostration<String> obj= new Demostration<>();
List<String> lis2 = obj.supplier().get();
Demostration<Integer> obj2= new Demostration<>();
List<Integer> lis3 = obj2.supplier().get();
//栗子3,生成数据
String desc = product(() -> new CompanySlave("coder"),e-> "\t姓名:"+e.getName()+"\t薪资:"+e.getSalary()+"\t是否加班:"+e.isWorkOvertime());
log.info("slave:{}",desc);
}
public static String product(
Supplier<? extends CompanySlave> supplier,
Function<CompanySlave,
String> function){
CompanySlave slave = supplier.get();
if (slave.getName()==null && "".equals(slave.getName())){
slave.setName("slave");
}
slave.setSalary(BigDecimal.ZERO);
slave.setWorkOvertime(true);
return function.apply(slave);
}
public Supplier<List<T>> supplier(){
// lambda
// return () -> new ArrayList<>();
// constructor reference
return ArrayList::new;
}
}
@Getter
@Setter
class CompanySlave{
String name;
BigDecimal salary;
boolean workOvertime;
public CompanySlave() {
}
public CompanySlave(String name) {
this.name = name;
}
@Override
public String toString() {
return "CompanySlave{" +
"name='" + name + '\'' +
", salary=" + salary +
", workOvertime=" + workOvertime +
'}';
}
}
//再看看jdk里Logger的使用
/**
* Log a message, which is only to be constructed if the logging level
* is such that the message will actually be logged.
* <p>
* If the logger is currently enabled for the given message
* level then the message is constructed by invoking the provided
* supplier function and forwarded to all the registered output
* Handler objects.
* <p>
* @param level One of the message level identifiers, e.g., SEVERE
* @param msgSupplier A function, which when called, produces the
* desired log message
* @since 1.8
*/
public void log(Level level, Supplier<String> msgSupplier) {
if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msgSupplier.get());
doLog(lr);
}
类似还有限定数据类型的函数式接口:
- IntSupplier
- LongSupplier
- DoubleSupplier
- BooleanSupplier
未完待续。。。