JDK8新特性之函数式接口

简介: 什么是函数式接口先来看看传统的创建线程是怎么写的

什么是函数式接口

先来看看传统的创建线程是怎么写的

Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("t1");
    }
});
t1.start();

再来看看使用了函数式接口是怎么写的

Thread t2 = new Thread(() -> System.out.println("t2"));
t2.start();

Runnable接口直接可以使用Lambda表达式来编写,这是因为Runnable接口是一个函数式接口,来看看Runnable的源码。

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

发现该接口加上了函数式接口的定义注解:@FunctionalInterface,表明该接口是一个函数式接口。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {
}

在JDK8中,除了Runnbale接口,还有像Comparator、Callable等接口都加上了该注解定义为函数式接口。

内置函数式接口

JDK8提供了几个内置的函数式接口,用在了许多API的地方,都可以拿来用,可以满足大部分应用。

//Consumer<T> - T作为输入,执行某种动作但没有返回值
Consumer<String> con = (x) -> {
    System.out.println(x);
};
con.accept("hello world");
//Supplier<T> - 没有任何输入,返回T
Supplier<String> supp = () -> {
    return "Supplier";
};
System.out.println(supp.get());
//Predicate<T> -T作为输入,返回的boolean值作为输出
Predicate<String> pre = (x) -> {
    System.out.print(x);
    return x.startsWith("op");
};
System.out.println(": " + pre.test("op, hello World"));
// Function<T, R> -T作为输入,返回的R作为输出
Function<String, String> function = (x) -> {
    System.out.print(x + ": ");
    return "Function";
};
System.out.println(function.apply("hello world"));
//BinaryOperator<T> -两个T作为输入,返回一个T作为输出,对于“reduce”操作很有用
BinaryOperator<String> bina = (x, y) -> {
    System.out.print(x + " " + y);
    return "BinaryOperator";
};
System.out.println("  " + bina.apply("hello ", "world"));

自定义函数式接口

1、自定义一个函数式接口

@FunctionalInterface
public interface CalcInterface<N, V> {  
    V operation(N n1, N n2);
}

这里只有一个抽象方法,@FunctionalInterface注解可以不用写,至于为什么可以往下看。

2、新建一个引用函数式接口的类

public static class NumberOperation<N extends Number, V extends Number> {
    private N n1;
    private N n2;
    public NumberOperation(N n1, N n2) {
        this.n1 = n1;
        this.n2 = n2;
    }
    public V calc(CalcInterface<N, V> ci) {
        V v = ci.operation(n1, n2);
        return v;
    }
}

3、测试函数式接口

private static void testOperationFnInterface() {
        NumberOperation<Integer, Integer> np = new NumberOperation(13, 10);
    CalcInterface<Integer, Integer> addOper1 = (n1, n2) -> {
        return n1 + n2;
    };
    CalcInterface<Integer, Integer> multiOper1 = (n1, n2) -> {
        return n1 * n2;
    };
    System.out.println(np.calc1(addOper1));
    System.out.println(np.calc1(multiOper1));
    // 上面的可以简写为
    System.out.println(np.calc1((n1, n2) -> n1 + n2));
    System.out.println(np.calc1((n1, n2) -> n1 * n2));
}

最后输出:

23
130
23
130

函数式接口规范

1、@FunctionalInterface标识为一个函数式接口只能用在只有一个抽象方法的接口上。


2、接口中的静态方法、默认方法、覆盖了Object类的方法都不算抽象方法。


3、@FunctionalInterface注解不是必须的,如果该接口只有一个抽象方法可以不写,它默认就符合函数式接口,但建议都写上该注解,编译器会检查该接口是否符合函数式接口的规范。


举例说明

正确的函数式接口。

@FunctionalInterface
public interface CalcInterface<N, V> {  
    V operation(N n1, N n2);
}

加了几个符合函数式的方法也没事,编译器也不会报错。

@FunctionalInterface
public interface CalcInterface<N, V> {      
    V operation(N n1, N n2);
    public boolean equals(Object object);
    public default void defaultMethod() {
    }
    public static void staticMethod() {
    }
}

这个没用@FunctionalInterface函数式接口,有两个抽象方法,不能用于Lambda表达式。

public interface CalcInterface<N, V> {  
    V operation(N n1, N n2);
    V operation2(N n1, N n2);
}

这个有两个抽象方法的用@FunctionalInterface注解的函数式接口编译会报错。

@FunctionalInterface
public interface CalcInterface<N, V> {  
    V operation(N n1, N n2);
    V operation2(N n1, N n2);
}

这个没有一个抽象方法,编译报错。

public interface CalcInterface<N, V> {  
}
相关文章
|
7月前
|
开发框架 Java 关系型数据库
在Linux系统中安装JDK、Tomcat、MySQL以及部署J2EE后端接口
校验时,浏览器输入:http://[your_server_IP]:8080/myapp。如果你看到你的应用的欢迎页面,恭喜你,一切都已就绪。
537 17
|
7月前
|
Java 关系型数据库 MySQL
在Linux操作系统上设置JDK、Tomcat、MySQL以及J2EE后端接口的部署步骤
让我们总结一下,给你的Linux操作系统装备上最强的军队,需要先后装备好JDK的弓箭,布置好Tomcat的阵地,再把MySQL的物资原料准备好,最后部署好J2EE攻城车,那就准备好进军吧,你的Linux军团,无人可挡!
167 18
|
7月前
|
开发框架 关系型数据库 Java
Linux操作系统中JDK、Tomcat、MySQL的完整安装流程以及J2EE后端接口的部署
然后Tomcat会自动将其解压成一个名为ROOT的文件夹。重启Tomcat,让新“植物”适应新环境。访问http://localhost:8080/yourproject看到你的项目页面,说明“植物”种植成功。
241 10
|
9月前
|
Java 测试技术 调度
JDK21有没有什么稳定、简单又强势的特性?
这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。
JDK21有没有什么稳定、简单又强势的特性?
|
容器
jdk8新特性-详情查看文档
jdk8新特性-详情查看文档
192 7
|
Java
让星星⭐月亮告诉你,jdk1.8 Java函数式编程示例:Lambda函数/方法引用/4种内建函数式接口(功能性-/消费型/供给型/断言型)
本示例展示了Java中函数式接口的使用,包括自定义和内置的函数式接口。通过方法引用,实现对字符串操作如转换大写、数值转换等,并演示了Function、Consumer、Supplier及Predicate四种主要内置函数式接口的应用。
138 1
|
容器
jdk8新特性-详情查看文档
jdk8新特性-详情查看文档
162 3
|
存储 安全 Java
JDK1.8 新的特性
JDK1.8 新的特性
172 0
|
5月前
|
存储 Ubuntu 安全
在Ubuntu 16.04上安装openjdk-6/7/8-jdk的步骤
在整个安装过程中,你可能需要管理员权限,因此你可能要使用 `sudo` 来获取必要的权限。记得做完每一个步骤后,都要检查输出,以确保没有发生错误,并且每项操作都成功完成。如果在安装过程中遇到问题,查看 `/var/log/` 下的日志文件对于问题的解决可能是有帮助的。
384 21
|
5月前
|
IDE Ubuntu Java
在Ubuntu18.04安装兼容JDK 8的Eclipse集成开发环境的指南。
完成以上步骤后,您将在Ubuntu 18.04系统上成功安装并配置了Eclipse IDE,它将与JDK 8兼容,可以开始进行Java开发工作。如果遇到任何问题,请确保每一步骤都正确执行,并检查是否所有路径都与您的具体情况相匹配。
259 11