JAVA函数式接口 与 匿名内部类、Lambda表达式、方法引用

函数式接口 (Functional Interface)

函数式接口主要指的是只包含一个抽象方法的接口,例如:java.lang.Runnable、java.util.Cpmparator接口等等。
java.lang.Runnable接口
Java8提供@FunctionalInterface注解来定义函数式接口,若定义的接口不符合函数式的规范,则会报错。在Java8中增加了java.util.function包(包内提供了大量的函数式接口):
java.util.function

匿名内部类

没有名字的内部类

语法格式:
父类/接口类型 引用变量名 = new 父类/接口类型(参数列表){
方法的重写
};

Lambda表达式

Lambda表达式是实现函数式接口的重要方式,利用Lambda表达式可以使代码变得更加简洁。

语法格式:(参数列表) -> { 方法体 };

函数式接口 与 匿名内部类、lambda表达式 (代码)

简单封装一个Person类备用

public class Person {
    private String name;
    private int age;
    public Person() {
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void show(){
        System.out.println("~(@^_^@)~咻咻咻");
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

下面的代码就是函数式接口的相关使用
在使用函数式内部类时,需要确定自己要使用的带不带参数,带几个参数,需不需要返回值。一些常用的函数式接口如下:

接口名称方法声明及功能介绍
Consumervoid accept(T t) ;根据指定的参数执行操作
SupplierT get() ; 得到一个返回值
Function<T,R>R apply(T t) ;根据指定的参数执行操作并返回
Predicateboolean test(T t) ;判断指定的参数是否满足条件

测试代码如下:

public class FunctionalInterface {

    public static void main(String[] args) {

        // 1. 匿名内部类的语法格式: 父类/接口类型 引用变量名 = new 父类/接口类型(){ 方法的重写 }
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("我是既没有参数又没有返回值的方法");
            }
        };
        runnable.run();

        // 2.使用lambda表达式实现函数式接口对象的实现
        //  一个参数可省略参数类型和小括号
        //  只有一条语句时可省略大括号
        //  只有一条语句且是return时,可省略大括号及return
        Runnable runnable1 = () -> System.out.println("lambda表达式实现的既没有参数又没有返回值的方法");
        runnable1.run();

        System.out.println("-----------------------------");

        Consumer consumer = new Consumer() {
            @Override
            public void accept(Object o) {
                System.out.println( o +"有参但没有返回值的方法");
            }
        };
        consumer.accept("友情提示1:");

        Consumer consumer1 = (Object o) -> System.out.println( o +"有参但没有返回值的方法");
        Consumer consumer2 = (o) -> System.out.println( o +"有参但没有返回值的方法");
        Consumer consumer3 = o -> System.out.println( o +"有参但没有返回值的方法");
        consumer1.accept("友情提示2");

        System.out.println("-----------------------------");

        Supplier supplier = new Supplier() {
            @Override
            public Object get() {
                return "我是一个无参有返回值的函数式接口方法";
            }
        };
        System.out.println(supplier.get());

        Supplier supplier1 = () -> {return "我是一个无参有返回值的函数式接口方法";};
        Supplier supplier2 = () ->  "我是一个无参有返回值的函数式接口方法";
        supplier1.get();

        System.out.println("------------------------------");


        Function function = new Function() {
            @Override
            public Object apply(Object o) {
                return o;
            }
        };
        System.out.println(function.apply("Function<T,r>是一个有参有返回值的函数式接口"));

        Function function1 = o -> o;
        System.out.println(function1.apply("11"));
    }
}

方法的引用

方法引用主要指通过方法的名字来指向一个方法而不需要为方法引用提供方法体,该方法的调用交给函数式接口执行。就是我通过类名或者对象名,直接指向该类或者该对象中的某一个方法。

匿名内部类、lambda和方法引用其实是相通的,从匿名内部类到lambda到方法引用是一个进化的过程,是一个简化的过程,更加是一个从抽象的过程。作用都是实现接口方法,换句话说就是实现接口;只是这个接口只有一个抽象方法。

方法的引用使用一对 :: 通过类或对象指向方法,通常使用方式如下:

  • 对象的非静态方法引用 ObjectName :: MethodName
  • 类的静态方法引用 ClassName ::StaticMethodName
  • 类的非静态方法引用 ClassName :: MethodName
  • 构造器的引用 ClassName :: new
  • 数组的引用 TypeName[] :: new

方法引用是在特定场景下lambda表达式的一种简化表示,可以进一步简化代码的编写使代码更加
紧凑简洁,从而减少冗余代码。

对应代码如下(跟课程练习时写的代码,太长了,慎看…):

public static void main(String[] args) {

        // 1.使用匿名内部类的方式通过函数式接口Runnable中的方法实现对Person中show方法的调用
        Person person = new Person("章法",13);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                person.show();
            }
        };
        runnable.run(); // ~(@^_^@)~咻咻咻

        System.out.println("--------------------------------------------------");
        // 2.使用lambda表达式的方式通过函数式接口Runnable中的方法实现对Person中show方法的调用
        Runnable runnable1 = () -> person.show();
        runnable1.run();// ~(@^_^@)~咻咻咻

        System.out.println("--------------------------------------------------");
        // 3.使用方法引用的方式实现Person类中show方法的调用
        Runnable runnable2 = person::show;  // 方法引用
        runnable2.run();


        System.out.println("--------------------------------------------------");
        // 4.使用函数内部类的方式实通过函数式接口Consumer中的方法实现Person中setName方法的使用
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                person.setName(s);
            }
        };
        consumer.accept("guanyu");
        System.out.println("Person = " + person);

        System.out.println("--------------------------------------------------");
        // 5.使用lambda表达式的方法实现Person类中setName方法的使用
        Consumer<String> consumer1 = s -> person.setName(s);
        consumer1.accept("liubei");
        System.out.println("Person = " + person);

        System.out.println("--------------------------------------------------");
        // 6.使用  方法引用 的方式使用Person类中serName方法的使用
        Consumer<String> consumer2 = person::setName;
        consumer2.accept("zhangfei");
        System.out.println("Person = " + person);


        System.out.println("--------------------------------------------------");
        // 7.使用函数内部类的方式实通过函数式接口Supplier中的方法实现Person中getName方法的使用
        Supplier<String> stringSupplier = new Supplier<String>() {
            @Override
            public String get() {
                return person.getName();
            }
        };
        System.out.println(stringSupplier.get());

        Supplier<String> stringSupplier1 = () -> person.getName();
        System.out.println(stringSupplier1.get());

        Supplier<String> stringSupplier2 = person::getName;
        System.out.println(stringSupplier2.get());


        System.out.println("--------------------------------------------------");
        // 8.(类的静态方法引用)使用匿名内部类的方式通过函数式接口Function中的方法实现Integer类中parseInt方法(将字符串转换为整数)的调用
        Function<String,Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.parseInt(s);
            }
        };
        System.out.println(function.apply("12345"));// 12345

        Function<String,Integer> function1 = s -> Integer.parseInt(s);
        System.out.println(function1.apply("12345"));// 12345


        Function<String,Integer> function2 = Integer::parseInt;
        System.out.println(function2.apply("12345")); // 12345

        System.out.println("--------------------------------------------------");
        // 9.(类的静态方法引用)使用匿名内部类的方式通过函数式接口Comparator中的方法实现Integer类中compare方法的调用
        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };
        System.out.println(comparator.compare(1, 2)); // -1

        Comparator<Integer> comparator1 = (o1,o2) -> Integer.compare(o1,o2);
        System.out.println(comparator1.compare(1, 2));  // -1

        Comparator<Integer> comparator2 = Integer::compare;
        System.out.println(comparator2.compare(1, 2));  // -1

        System.out.println("--------------------------------------------------");
        // 10.(类的静态方法引用)使用匿名内部类的方式通过类名来调用非静态方法
        // 其中一个参数作为调用对象来调用方法时,可以使用上述方式  更加抽象
        Comparator<Integer> comparator3 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };
        System.out.println(comparator3.compare(1, 2));  // -1

        Comparator<Integer> comparator4 = (o1, o2) -> o1.compareTo(o2);
        System.out.println(comparator4.compare(1, 2));  // -1


        Comparator<Integer> comparator5 = Integer::compareTo;
        System.out.println(comparator5.compare(1, 2));  // -1

        System.out.println("--------------------------------------------------");
        // 11.(构造器的引用)使用匿名内部类的方式通过Supplier函数式接口采用无参方式创建Person类型的对象并返回
        Supplier<Person> supplier = new Supplier<Person>() {
            @Override
            public Person get() {
                return new Person();
            }
        };
        System.out.println(supplier.get());   // Person{name='null', age=0}

        Supplier<Person> supplier1 = () -> new Person();
        System.out.println(supplier1.get());   // Person{name='null', age=0}

        Supplier<Person> supplier2 = Person::new;
        System.out.println(supplier2.get());   // Person{name='null', age=0}

        System.out.println("--------------------------------------------------");
        // 12.(构造器的引用)使用匿名内部类的方式通过BiFunction函数式接口采用有参方式创建Person类型的对象并返回
        BiFunction<String,Integer,Person> biFunction = new BiFunction<String, Integer, Person>() {
            @Override
            public Person apply(String s, Integer integer) {
                return new Person(s,integer);
            }
        };
        System.out.println(biFunction.apply("zhanfei", 30));  // Person{name='zhanfei', age=30}

        BiFunction<String,Integer,Person> biFunction1 = (s,integer)->new Person(s,integer);
        System.out.println(biFunction1.apply("liubei", 40));   // Person{name='liubei', age=40}

        BiFunction<String,Integer,Person> biFunction2 = Person::new;
        System.out.println(biFunction2.apply("guanyu", 35));   // Person{name='guanyu', age=35}


        System.out.println("--------------------------------------------------");
        // 12.(数组的引用)使用匿名内部类的方式通过Function函数式接口采用创建指定数量的Person类型的对象数组并返回
        Function<Integer,Person[]> function3 = new Function<Integer, Person[]>() {
            @Override
            public Person[] apply(Integer integer) {
                return new Person[integer];
            }
        };
        System.out.println(Arrays.toString(function3.apply(3)));   // [null, null, null]

        Function<Integer,Person[]> function4 = integer -> new Person[integer];
        System.out.println(Arrays.toString( function4.apply(4)));   // [null, null, null, null]

        Function<Integer,Person[]> function5 = Person[]::new;
        System.out.println(Arrays.toString(function5.apply(5)));    // [null, null, null, null, null]
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值