λ表达式

λ表达式是一个可传递的代码块,可以执行一次或者多次。

基本形式:参数 -> 表达式

例如:

(String first,String second)->first.length()-second.length()

字符串按长度排序:

String[] strs=new String[]{"abc","ab","abcd","Hello,Jack"};
//        Arrays.sort(strs,(String first,String second) ->{
//            return first.length() - second.length();
//        });
        Arrays.sort(strs,( first, second) -> first.length()-second.length());
        for (int i=0;i<strs.length;i++)
        {
            System.out.print(strs[i]+" ");
        }

注意:

  1. 如果表达式里的代码不能一句表达,可以像写方法一样,放到一个花括号里,并包含return语句。

     String[] strs=new String[]{"abc","ab","abcd","Hello,Jack"};
            Arrays.sort(strs,(String first,String second) -> {
                return first.length()-second.length();
            });
    
  2. 即使没有参数,仍然要包含空括号。

  3. 如果可以推导出参数类型,则可以忽略其类型不写。

  4. 如果表达式只有一个参数,且这个参数的类型可以推导出来,则可以忽略小括号。

  5. λ表达式的返回值无需指定,总是可以由上下文推导得出。

    Arrays.sort(strs,(first,second) -> first.length()-second.length());
    

    函数式接口

    定义:如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口。

    如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口。

    函数式接口的使用:使的我们可以将方法当作参数来传递。在调用时,lambda 表达式作为参数来使用。换句话说,当一个方法的参数是 lambda 表达式时,这个参数类型一定是函数式接口。

@FunctionalInterface
public interface LambdaTestasd {

    static void out(){
        System.out.println("这是一个函数式接口");
        System.out.println("这是接口里的静态方法");
    }

    default void print(){
        System.out.println("这是接口里的默认方法");
    }
    void test();
}

在 java8 中的 java.util.function包中,包含了几大类函数式接口声明:

	//Consumer<T>消费型接口
    @Test
    public void test1(){
        Consumer<String> c = (x) -> System.out.println("hello:"+x);
        c.accept("java");   //hello:java
    }
    
    //Supplier<T>供给型接口
    @Test
    public void test2(){
        Supplier<String> s = () -> "hello";
        String str = s.get();
        System.out.println(str);    //hello
    }
    
    //Function<T,R>函数型接口
    @Test
    public void test3(){
        Function<String,Integer> f = (x) -> x.length();
        Integer len = f.apply("hello");
        System.out.println(len);    //5
    }
    
    //Predicate<T>断定型接口
    @Test
    public void test4(){
        Predicate<String> p = (x) -> x.length() > 5;
        boolean b = p.test("hello java");
        System.out.println(b);  //true
    }

方法引用

定义:方法引用 是用来直接访问类或者实例的已经存在的方法或者构造方法。

通过方法引用来简写lambda表达式中已经存在的方法。

例如:

var timer=new Timer(1000,event->System.out.println(event));

改为方法引用:

var timer=new Timer(1000,System.out::println);

方法引用主要有三种:

1. 类名::静态方法名
2. 对象::实例方法名
3. 类名::实例方法名 

λ表达式的作用域问题

  1. 在λ表达式中只能引用值,不能改变变量的值。
  2. 如果λ表达式引用的一个变量,而这个变量可能再外部改变,也是不合法的。
  3. λ表达式中捕获的变量必须实际上是事实最终变量(effetively final)。(事实最终变量是指这个变量初始化之后就不会再为它赋新值。)
  4. λ表达式的体与嵌套块有相同的作用域。在λ表达式中声名一个与局部变量同名的参数或者局部变量是不合法的。
  5. 在一个λ表达式中使用this关键词时,是指创建这个λ表达式的方法的this参数。
posted @ 2020-04-21 19:28  hellowen2020  阅读(607)  评论(0)    收藏  举报