认识JDK8新特性之Lambda表达式

说来挺惭愧的,JDK8已经出来这么多年,在实际项目中却不多真正使用Lambda表达式。其实工做中的项目很早就从开发、测试、生产,全面使用JDK8+Tomcat8了。html

因此看来是时候要从新认识下这个奇怪的东西。java

没错,当第一次看到Lambda表达式时,我就认为这是个奇怪的东西,->写法让我感受这是在写其它语言,说好的一切皆对象呢?oracle

表达式语法

这是Lambda表达式的基本语法:app

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
    statment1;
    statment2;
    //......
    return statmentM;
}

参数列表是一个逗号分隔的形式参数列表,这些参数与功能接口中单一方法的形式参数相对应。指定参数类型是可选项;若是未指定参数类型,将从上下文推断。参数列表必须用括号括起来,但当指定的单一参数不带参数类型时除外;指定单一形式参数时能够不带括号。若是功能接口方法不指定任何形式参数,则必须指定空括号。测试

语句块必须包含在大括号内,除非语句块是一个方法调用语句。ui

举个简单例子

对于无参无返回值,能够有以下写法:this

public interface TestIntf {
    public void sayHello();
}

// -> 前的一对小括号和后面的一对大括号都不能去掉。
TestIntf intf = () -> {System.out.println("HelloWorld!!!");};
intf.sayHello();

对于有参有返回值,能够有以下写法:code

public interface TestIntf {
    public String sayHello(String word);
}

// 完整写法
TestIntf intf = (String word) -> {return "Hello " + word;};

// 参数word的类型能够推断时,能够去掉类型定义:
TestIntf intf = (word) -> {return "Hello " + word;};

// 甚至当参数只有一个时,能够去掉左边的小括号:
TestIntf intf = word -> {return "Hello " + word;};

// 右侧的方法体只有一个表达式时,能够去掉大括号,甚至连return均可以不要:
TestIntf intf = word -> "Hello " + word;

变量做用域

Lambda表达式内部能够访问外部的变量,但须要注意:htm

局部变量不管是在Lambda表达式主体中声明,仍是在封闭做用域中声明,使用以前都必须先初始化。如:对象

interface TestIntf {
    public String sayHello(String word);
}

public class App {
    public static void main(String[] args) {
        String str;
        TestIntf intf = (String word) -> {
            System.out.println(str); // 编译失败,提示str变量未被初始化。
            return "Hello " + word;
        };
    }
}

Lambda表达式不会定义新的做用域;Lambda表达式的做用域与封闭做用域相同。如:

interface TestIntf {
    public String sayHello(String word);
}

public class App {
    public static void main(String[] args) {
        String str = "word";
        TestIntf intf = (String word) -> {
            String str = ""; // 编译失败,提示str变量重复定义了。
            return "Hello " + word;
        };
    }
}

并且也不能修改外部变量:

interface TestIntf {
    public String sayHello(String word);
}

public class App {
    public static void main(String[] args) {
        String str = "word";
        TestIntf intf = (String word) -> {
            str = "word!!!"; // 编译报错:Local variable str defined in an enclosing scope must be final or effectively final
            return "Hello " + word;
        };
    }
}

固然,引用变量是能够经过内部方法达到数据修改的。

interface TestIntf {
    public String sayHello(StringBuilder word);
}

public class App {
    public static void main(String[] args) {
        StringBuilder str = new StringBuilder("word");
        TestIntf intf = (StringBuilder word) -> {
            word.append("!!!");
            return "Hello " + word;
        };
        System.out.println(intf.sayHello(str)); // Hello word!!!
        System.out.println(str); // word!!!
    }
}

Lambda表达式中的this

在Lambda表达式中this引用的不是Lambda表达式对象,而是声明它的外部对象:

interface TestIntf {
    public String sayHello();
}

public class App {
    
    public void test() {
        TestIntf intf = () -> "Hello " + this.getClass().getSimpleName();
        System.out.println(intf.sayHello());
    }
    
    public static void main(String[] args) {
        App app = new App();
        app.test(); // Hello App
    }
}

参考文章

https://www.oracle.com/techne...

相关文章
相关标签/搜索