zoukankan      html  css  js  c++  java
  • java8函数式接口@FunctionalInterface

    TOC

    函数式接口@FunctionalInterface

    研究之前最好学习一下Lambda 表达式

    参考

    函数式接口概述

    所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法

    这种类型的接口也称为SAM接口,即Single Abstract Method interfaces

    在 Java 中,Marker(标记)类型的接口是一种没有方法或属性声明的接口,简单地说,marker 接口是空接口。相似地,函数式接口是只包含一个抽象方法声明的接口

    java.lang.Runnable 就是一种函数式接口,在 Runnable 接口中只声明了一个方法 void run(),相似地,ActionListener 接口也是一种函数式接口,我们使用匿名内部类来实例化函数式接口的对象,有了 Lambda 表达式,这一方式可以得到简化。

    每个 Lambda 表达式都能隐式地赋值给函数式接口,例如,我们可以通过 Lambda 表达式创建 Runnable 接口的引用。

    Runnable r = () -> System.out.println("hello world");

    当不指明函数式接口时,编译器会自动解释这种转化:

    new Thread(
       () -> System.out.println("hello world")
    ).start();

    因此,在上面的代码中,编译器会自动推断:根据线程类的构造函数签名 public Thread(Runnable r) { },将该 Lambda 表达式赋给 Runnable 接口。

    以下是一些 Lambda 表达式及其函数式接口:

    Consumer<Integer>  c = (int x) -> { System.out.println(x) };
    BiConsumer<Integer, String> b = (Integer x, String y) -> System.out.println(x + " : " + y);
    Predicate<String> p = (String s) -> { s == null };

    @FunctionalInterface是 Java 8 新加入的一种接口,用于指明该接口类型声明是根据 Java 语言规范定义的函数式接口。Java 8 还声明了一些 Lambda 表达式可以使用的函数式接口,当你注释的接口不是有效的函数式接口时,可以使用 @FunctionalInterface解决编译层面的错误。

    特点

    • 接口有且仅有一个抽象方法(abstract)
    • 允许定义静态方法static
    • 允许定义默认方法default
    • 允许java.lang.Object中的public方法
    • 该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错

      符合函数式接口的,可以不加这个注解,不是函数式接口的加了注解会报错(建议加上,否则被别人改了还不报错就坏了)

    定义

    比如可以这样定义

    @FunctionalInterface
    public interface WorkerInterface { 
        //抽象关键字可以省略
        public void doSomeWork();
        //public void doSomeMoreWork();//根据定义,函数式接口只能有一个抽象方法,如果你尝试添加第二个抽象方法,将抛出编译时错误。
    }
    //若是加上第二个抽象方法会报错
    Unexpected @FunctionalInterface annotation
        @FunctionalInterface ^ WorkerInterface is not a functional interface multiple
        non-overriding abstract methods found in interface WorkerInterface 1 error

    也可以

    // 正确的函数式接口
    @FunctionalInterface
    public interface TestInterface {
    
        // 抽象方法
        public void sub();
    
        // java.lang.Object中的public方法,可以留着
        public boolean equals(Object var1);
    
        // 默认方法 default可以
        public default void defaultMethod(){
    
        }
    
        // 静态方法 static方法可以
        public static void staticMethod(){
    
        }
    }
    
    // 错误的函数式接口(有多个抽象方法)
    @FunctionalInterface
    public interface TestInterface2 {
    
        void add();
    
        void sub();
    }
    

    使用

    • 案例1
    //定义一个函数式接口
    @FunctionalInterface
    public interface WorkerInterface {
        public void doSomeWork();
    }
    public class WorkerInterfaceTest {
        public static void execute(WorkerInterface worker) {
            //传入实现的函数式接口类,调用接口方法
            worker.doSomeWork();
        }
        public static void main(String[] args) {
            //普通调用方法
            execute(new WorkerInterface() {
                //调用WorkerInterface,实现接口
                @Override
                public void doSomeWork() {
                    System.out.println("Worker invoked using Anonymous class");
                }
            });
            //Lambda 优化
            execute(() -> System.out.println("Worker invoked using Lambda expression"));
        }
    }
    /////////
    输出:
    Worker invoked using Anonymous class
    Worker invoked using Lambda expression




  • 相关阅读:
    .Net常识 值类型和引用类型
    .net 开发人员的瓶颈和职业发展
    PPT Garbage Collection in .Net (内存管理)
    Why Sessionless Web Application ?
    一些.Net面试题 (BS 方向)
    开源一个小类库, 用于对象间灵活的拷贝属性,还有IDataReader到实体类的转换
    在 Visual Studio 单元测试中使用CallContext 导致的 Unit Test Adapter threw exception: Type is not resolved for member... 异常
    【设计原则和建议】 类
    轻量级 Lock Free 线程安全的 Queue<T> 的C#2.0实现
    实验一 命令解释程序的编写
  • 原文地址:https://www.cnblogs.com/ziyue7575/p/c3a8359c44b7e519f12eb004d33f4b44.html
Copyright © 2011-2022 走看看