Java8新特性之Lambda表达式学习二

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/super_YC/article/details/81260338

大家好,又来到超超博客大本营啦!欢迎大家......

上一章我们讲解了Lambda表达式的基础语法,参数列表、变量等知识点,接下来我们接续探究Lambda的表达式、以及其中的方法引用。

一、Lambda的表达式:

(1)如果表达式只有一行,那么可以直接写(不需要{});

(2)如果表达式有多行,就需要用{}变成代码块,就应该要符合正常的Java语法;

(3)如果表达式是代码块,并且方法需要返回值,那么在代码块中就必须要返回一个该类型的值;

(4)如果只有单行的情况,并且方法需要返回值,不能有return,因为此时是表达式,而不是代码块,编译器会自动帮我们推导出return的返回值;

例1:依然是字符串数组排序

    public void test2(){
        String[] strs = new String[]{"Android","IOS","Java","OS"};
        /**
         * Lambda表达式若有多行,就需要用{}变成代码块,就应该要符合正常的Java语法
         */
        Arrays.sort(strs,(final String s1,final String s2) ->{
            if(s1 != null && s2 != null) {
                return Integer.compare(s1.length(), s2.length());
            }
            return -1;
        });
        System.out.println(Arrays.toString(strs));

        //只有单行,并且方法需要返回值,不能有return,因为此时是表达式,而不是代码块,编译器会自                    
           动帮我们推导出return的返回值;
         Arrays.sort(strs,(final String s1,final String s2) -> Integer.compare(s1.length(), s2.length()));
         
        System.out.println(Arrays.toString(strs));
    }

二、Lambda表达式中的方法引用:

(1) 类::静态方法

例2:继续改造整型数组元素的排序

   public void testLambda() {
        Integer[] arr = new Integer[]{2, 5, 3, 8, 6, 10, 9};
        /**
         * 第一:Comparator接口中的compare()方法的两个参数(x,y),原封不动的直接传递给了Integer.compare()方法;
         * 第二:可以直接将其Integer中的compare()方法看成是Comparator接口中的compare()方法的实现,参数类型、参数个数、方法返回值相同,方法名可以不相同哈;
         */
        Arrays.sort(arr,(x,y) -> Integer.compare(x, y));
        System.out.println(Arrays.toString(arr));

        /**
         * 借于上述,可以继续改写Lambda表达式;
         * 使用方法引用(类::静态方法)
         */
        Arrays.sort(arr, Integer::compare);
        System.out.println(Arrays.toString(arr));
    }

(2) 对象::方法

例3:直接输出数组中的元素列表

   public void testLambda() {
        List<Integer> list = Arrays.asList(2, 5, 3, 8, 6, 10, 9);

        //原生的写法
        list.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer x) {
                System.out.println(x);
            }
        });
        System.out.println(Arrays.toString(arr));

        /* Lambda表达式简化操作
         * 第一:System.out是一个PrintStream对象,println()是该对象的一个方法;
         * 第二:println(Obejct x)这个方法本身需要传入一个Object对象;
         * 第三:而打印x就是直接将x对象原封不动的交由System.out.println()这个方法,然后调用对象的toString()方法打印即可;
         * 第四:我们就可以理解为System.out对象的println()方法,在其调用了对象toString()方
         * 法,就是替代了Consumer接口中的accept()方法(需要满足:方法参数类型个数相同,返回值相
         * 同,方法名可以不同);
         */
        list.forEach(System.out::println);

        System.out.println(Arrays.toString(arr));
    }

(3) 对象::静态方法(自己举例,不在赘述)

(4) 类::new      ==>不好理解,需要下来继续揣摩 (本质上还是函数式接口,匿名内部类的改写)

首先我们先定义一个函数式接口:

注意构造器引用对应的函数式接口里面的方法格式一定是:返回一个对象

import java.util.List;

@FunctionalInterface
public interface IMyCreator<T extends List<?>> {

    T create();

}

其次,书写我们的Lambda表达式:

public class TestLambda {
    
    //改装Arrays中的asList()方法
    public <T> List<T> asList(IMyCreator<List<T>> creator, T... a) {
        List<T> list = creator.create();
        for (T t : a) {
            list.add(t);
        }
        return list;
    }

    @Test
    public void test() {

        //使用匿名内部类创建对象
        List<Integer> list1 = this.asList(new IMyCreator<List<Integer>>() {
            @Override
            public List<Integer> create() {
                return new ArrayList();
            }
        },2,3,4,5,6);

        /**
         * 第一:asList()方法第一个参数,一定是IMyCreator接口的实例;
         * 第二:创建IMyCreator接口实例,一定要重写create()方法;
         * 第三:重写create()方法,一定要返回一个泛型 T 的对象(T 和传入类型等同);
         * 这些都是JVM帮助我们自动补全,可以改写为下面Lambda表达式。
         */
        List<Integer> list2 = this.asList(() -> {
            return new ArrayList();
        }, 3, 4, 5, 6);

        //继续改写
        List<Integer> list3 = this.asList(() -> new ArrayList(),2,3,4,5,6);

        //最终改写,使用构造方法引用,类::new
        List<Integer> list4 = this.asList(ArrayList::new, 2, 3, 4, 5, 6);
        list4.forEach(System.out::println);
    }

}

三、自己实现一个函数式接口,并将匿名内部类改写为Lambda表达式

先创建一个接口,并用@FunctionInteface修饰

@FunctionalInterface
public interface IMyWork {

    public void doWork();

}

简单实现: 

    @Test
    public void testLambda(){
        IMyWork work = () -> System.out.print("this is @FunctionInterface");
        work.doWork();
    }

注意要点:

第一:我们能写Lambda表达式的地方?需满足一个接口,且接口里面只有一个抽象方法;

第二:在Java中,把只有一个抽象方法的接口称为函数式接口,如果一个接口是函数式接口,我们可以在接口上添加@FunctionInterface,表明这是一个函数式接口;(1、自动检查;2、文档) 

第三:无论是否标识@FunctionInterface,只要满足函数式接口的接口,Java都会识别为函数式接口;

第四:简化函数式接口的使用是Java中提供Lambda表达式唯一的作用;

第五:可以用接口直接来引用一个Lambda表达式;

第六:Lambda表达式中的异常处理:Lambda表达式中产生的异常,要么在代码块中直接处理,要么在接口的方法声明抛出;

好啦,Lambda表达式基础语法、简单使用都讲解完了,接下来就需要大家灵活应用于平常的Java代码中,使得自己的Java代码干净,整洁!有啥问题,请大家及时指出,很希望一起进步努力......

学习完超超的Lambda表达式,还不来看看Stream的基础知识:Java8新特性之Stream详解

猜你喜欢

转载自blog.csdn.net/super_YC/article/details/81260338