Java函数式接口详解(定义作用及应用示例)

Java函数式接口详解(定义作用及应用示例)-mikechen

Java函数式接口定义

Java函数式接口,英文名Functional Interface,就是有且仅有一个抽象方法的接口,但是可以有多个非抽象方法的接口,就是函数式接口。

Java Lambda就是Java中函数式编程的体现,可以使用Lambda表达式创建一个函数式接口的对象。

 

Java函数式接口语法

Java函数式接口格式:只要确保接口中有且仅有一个抽象方法即可。

语法:

修饰符 interface 接口名称 {
public abstract 返回值类型 方法名称(可选参数信息);
// 其他非抽象方法内容
}

示例:

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

这个就一个函数式接口。

 

@FunctionalInterface注解

Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。

该注 解可用于一个接口的定义上:

@FunctionalInterface
public interface MyFunctionalInterface { void myMethod();
}

一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。

需要注 意的是:即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。

 

Java函数式接口使用

1.新建一个 ​​MyInterface​​ 函数式接口

示例如下:

/**
 * @author mikechen
 */
@FunctionalInterface
public interface MyInterface {
    void mikechensay();
}

 

2.使用匿名内部类的方式来进行使用

示例如下:

/**
 * @author mikechen
 */
public class Main {
    public static void main(String[] args) {
 
        MyInterface myInterface = new MyInterface() {
            @Override
            public void mikechensay() {
                System.out.println("hello 函数式接口");
            }
        };
 
        myInterface.mikechensay();
    }
}

 

3.还可以使用 Java Lambda 表达式简化使用

示例如下:

/**
 * @author mikechen
 */
public class Main {
    public static void main(String[] args) {
        MyInterface myInterface = () -> System.out.println("函数式接口");
        myInterface.mikechensay();
    }
}

 

Java函数式接口的应用

1.作为方法的参数

public class Main {
    public static void main(String[] args) {
        startThread(() -> System.out.println("线程启动"));
    }
 
    private static void startThread(Runnable runnable) {
        new Thread(runnable).start();
    }

 

2.作为方法的返回值

public class Main {
    public static void main(String[] args) {
        List<String> array = new ArrayList<>();
 
        array.add("BNTang");
        array.add("Jonathan_Lee");
        array.add("bbb");
        array.add("aa");
        array.add("cccc");
 
        System.out.println("排序前" + array);
 
        Collections.sort(array);
 
        System.out.println("排序后" + array);
 
        Collections.sort(array, getComparator());
    }
 
    private static Comparator<String> getComparator() {
        Comparator<String> comp = new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        };
        return (String s1, String s2) -> {
            return s1.length() - s2.length();
        };
    }
}

 

Java函数式接口示例

public class FunctionalInterfaceTest {

    // 1.写了一个方法,参数是函数式接口,你可以传递Runnable的实现,也可以使用Lambda或方法引用
    public static void execute(Runnable runnable) {
        try {
            runnable.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // 2.传入匿名对象
        execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名对象");
            }
        });

        // 3.使用Lambda,()表示Runnable#run()的参数,println()是Runnable#run()的方法体
        execute(() -> System.out.println("使用lambda"));

        // 5.因为wrapPrintln和上面的println做的是同样的事,可以替换
        UserService userService = new UserService();
        execute(() -> userService.wrapPrintln());
        
        // 6.IDEA提示上面的代码可以优化成 方法引用
        execute(userService::wrapPrintln);
        
        // 8.你会发现上面的写法仍是对的,因为“仅有一个抽象方法”是对Runnable的约束,不要搞混
    }

    // 4.我们试着把println()移到wrapPrintln中
    static class UserService {
        public void wrapPrintln() {
            System.out.println("包装后的println");
        }

        // 7.给UserService新增一个方法
        public void anotherMethod() {
            System.out.println("另一个方法,不影响execute使用wrapPrintln");
        }
    }
}

 

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法