【有书共读】Java攻略 读书笔记01
  一、Lambda表达式简介  
   “Lambda 表达式”(lambda expression)是一个匿名函数,即没有函数名的函数;Lambda表达式不仅让代码变的简单、而且可读、最重要的是代码量也随之减少很多。 
   Java Lambda表达式的一个重要用法是简化某些匿名内部类(Anonymous Classes)的写法。 
   二、Lambda基础语法  
   基本语法:(parameters) -> expression或(parameters) ->{ statements; }  
   下面是一些Java lambda表达式的简单例子: 
 () -> 1 // 1. 不需要参数,返回值为 1 x -> 3 * x // 2. 接收一个参数(数字类型),返回其3倍的值 (x, y) -> x + y // 3. 接受2个参数,并返回x+y (int x, int y) -> x + y // 4. 接收2个int型整数,返回两值的和 (String s) -> System.out.print(s) // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
  三、lambda取代某些匿名内部类  
   下面介绍如何使用Lambda表达式简化匿名内部类的书写,但Lambda表达式并不能取代所有的匿名内部类,只能用来取代函数式接口(Functional Interface)的简写。 
   函数式接口是一种包含单一抽象方法(single abstract method)的接口。类通过为接口中的所有方法提供实现来实现任何接口,这可以通过顶级类、内部类甚至匿名内部类完成。 
   3.1 无参函数的简写  
   ·例子1-1 Runnable接口的匿名内部类实现  
 public class  RunnableDemo{
    public static void main(String[] args) {
        new Thread(new Runnable(){// 接口名
            public void run(){// 方法名
                System.out.println("run test()");
            }
        }).start();
//以上代码给Tread类传递了一个匿名的Runnable对象
//重载Runnable接口的run()方法来实现相应逻辑
    }
}   例子1-2 使用lambda表达式改写以上代码  
 public class  RunnableDemo{
    public static void main(String[] args) {
        new Thread(() -> System.out.println("run test()")).start();
        // 省略接口名和方法名        
    }
}    在本例中,由于println方法返回的是void,所以对应的表达式同样会返回void,与run方法的类型相匹配 
   lambda表达式必须匹配接口中单一抽象方法签名的参数类型和返回类型,这被称为与方法签名兼容。所以,lambda表达式属于接口方法的实现,可以将其赋给该接口类型的引用。 
   比如上述例子,若要将lambda赋给函数式接口引用可以通过以下例子1-3实现:  
 Runnable runnable =() -> System.out.println("run test()");
new Thread(runnable).start();    3.2 有参函数的简写  
   例子1-4 FilenameFilter的匿名内部类实现  
 import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
public class FilenameFilterDemo {
    public static void main(String[] args) {
        File directory = new File("src/test/resources");
        String[] names = directory.list(new FilenameFilter() {    
            public boolean accept(File dir, String name) {
                return name.endsWith(".txt");
            }
        });
        System.out.println(Arrays.asList(names));
    }
}
   例1-5 采用lambda表达式改写以上代码  
 import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
public class FilenameFilterDemo {
    public static void main(String[] args) {
        File directory = new File("src/test/resources");
        String[] names = directory.list((dir,name)-> name.endsWith(".txt"));
        System.out.println(Arrays.asList(names));
    }
}    可以看到,代码要简单的多。参数包含在小括号中,但并未声明类型。在编译时,编译器发现list方法传入一个FilenameFilter类型的参数,从而获知其单一抽象方法accept的签名,进而了解accept的参数为File和String,因此兼容的lambda表达式参数必须匹配这些类型。由于accept方法返回的类型是布尔值,所以箭头右边的表达式也必须是返回布尔值。 
   我们也可以在代码中指定数据类型,如下例1-6所示:  
 File directory = new File("src/test/resources");
String[] names = directory.list((File dir,String name)-> name.endsWith(".txt"));    此外,如果lambda表示的实现多于一行,则需要使用大括号和显示返回语句,如例1-7所示:  
 File directory = new File("src/test/resources");
        
String[] names = directory.list((File dir,String name)-> {
        return name.endsWith(".txt");
    }
);    这就是lambda代码块,在本例中,虽然代码主体只有一行,但是可以使用大括号将多个语句括起来。注意,不能省略return关键字。 
   lambda表达式在任何情况下都不能脱离上下文存在,上下文指定了将表达式赋予给哪个函数式接口。lambda表达式既可以是方法的参数,也可以是方法的返回函数,还可以被赋给引用。无论哪种情况,赋值类型必须为函数式接口。 
#笔记##Java##读书笔记#

