应用于匿名内部类

  • 首先,匿名内部类一般都作为某个方法的参数实现某种功能,且多数是接口,需要重写某个方法
  • 没有使用Lambda的老方法

    button.addActionListener(new ActionListener(){
        //重写唯一方法
        public void actionPerformed(ActionEvent actionEvent){
            System.out.println("Action detected");
        }
    });
    
  • 以上的括号中大段代码里,只有第8行是真正起作用的,如果我们使用Lambda,那么只需要考虑这唯一起作用的一行

    button.addActionListener( ()->{
        System.out.println("Action detected");
    })
    
  • 让我们来看一个更明显的例子:
  • 不采用Lambda的老方法

    //重写方法
    Runable runable=new Runable(){
        @Override
        public void run(){
            System.out.println("Running without Lambda");
        }
    }
    //调用方法
    runnable.run();
    
  • 使用Lambda

    //重写方法
    Runnable runnable=() -> { System.out.println("Running from Lambda"); };
    //调用方法
    runnable.run();
    
  • 说白了Lambda语法就是用来代替实例化一个接口并重写其抽象方法的。

    语法

  • 下面是一些Lambda表达式:

    (int x,int y) -> x+y //接收x和y两个参数并返回它们的和
    () -> 42 //不接收参数,返回42
    (String s) -> {System.out.println(s);} //接收一个字符串并打印,不返回值
    
  • Lambda表达式的语法由参数列表、箭头符号->和函数体组成。函数体既可以是一个表达式,也可以是一个语句块:

    • 表达式:表达式会被执行并返回执行结果;适合小型的Lambda表达式,它消除了return关键字,使得语句更加简洁。
    • 语句块:语句块中的语句会被依次执行,就像方法中的语句一样

      FileFilter java=(File f) -> f.getName().endsWith(“*.java”);

      String user=doPrivileged(() -> System.getProperty(“user.name”);

      new Thread() -> {
          connectToService();
          sendNotification();
      }).start();
      
  • 对于上面的代码,FileFilter必须是接口,而且该接口只能有一个未实现的方法,即函数式接口。在定义接口时加上@FunctionalInterface即可限制该接口只能有一个方法。
  • 对于给定的Lambda表达式,它的类型是又其上下文推导而来的,不过它对目标类型也是有要求的,当且仅当下面的所有条件均满足时,Lambda表达式才可以被赋予目标类型T:
    • T是一个函数式接口
    • lambda表达式的参数和T的方法参数在数量和类型上一一对应
    • lambda表达式的返回值和T的方法返回值相兼容(Compatible)
    • lambda表达式内所抛出的异常和T的方法throws类型相兼容
  • 当Lambda的参数只有一个而且它的类型可以被推导得之,该参数列表外面的括号可以省略

    FileFilter java=f -> f.getName.endsWith(".java");
    
    button.addActionListener(e -> ui.dazzle(e.getModifiers()));
    
  • 完整例子

    //定义一个接口,注意,只能有一个未实现的方法
    public interface Formula<F,T> {
        T convert(F form);
    }
    
    //调用
    /*Lambda*/
    Formula<String,Integer> formula=(from) -> Integer.valueOf(from);
    Integer converted=formula.convert("123");
    System.out.println(converted+1);  //124
    
    /*简写*/
    Formula<String,Integer> formula=Integer::valueOf;
    Integer converted=formula.convert("123");
    System.out.println(converted+1);  //124
    
    Button button=new Button();
    button.addActionListener((e) -> {System.out.println("Action detected"+e);});
    

    简写

  • 范式
    • 类名::(静态|普通)方法名
    • 对象::(普通)方法名
  • 方法调用
    • x -> System.out.println(x)简写为System.out::println(out是一个PrintStream类的对象,println是该类的方法,依据x的类型来重载方法,至于要打印的这个x是谁,应该是根据上下文推断而来的)
    • person -> person.getAge()简写为Person::getAge()
  • 创建对象
    • () -> new ArrayList<>()简写为ArrayList::new(new关键字实际是调用ArrayList的构造方法)