java中lambda表达式的基本使用

java中lambda表达式的基本使用

在java中使用lambda表达式的话,需要注意两点:

  • 一个是lambda表达式本身的语法
  • 另一个是函数式接口

lambda语法

java8新增了一个操作符->,称为lambda操作符或箭头操作符,它将lambda表达式分为两部分,箭头之前的是参数,箭头之后的是动作。例如:

(int i, int j) -> i+j; 

相当于:

public int add(int i, int j)
{
    return i+j;
}

参数的类型也可以省略,java编译器会根据上下的语义推断出来:

(i, j) -> i+j;

如果只有一个参数,括号也可以省略:

i -> i+i;

若没有参数,则括号不能省略:

() -> System.out.println("helloworld!");

箭头的右边也可以是代码段,这个代码段可以写很长:

() -> {
    System.out.println("helloworld!");
    ...
    }

lambda和接口结合

在java中,lambda表达式一定要结合functional interface来使用,functional interface是指一个只包含一个抽象方法的接口。下面来看一个例子。这是一个functional interface:

public interface myInterface
{
    public void run(int num);
}

然后,声明一个该类型的lambda表达式:

myInterface mif = num -> num * num;
int i = mif.run(6);

两个参数的例子也是一样:

public interface myInterface
{
    public void run(int x , int y);
}

声明lambda表达式:

myInterface mif = (x, y) -> x + y;
int i = mif.run(5,6);

当然,使用代码块也能使lambda表达式更加复杂。


变量捕获
说到lambda表达式,有一个话题是绕不开的,就是闭包。但这个问题在java中被简化了好多。这个问题可以分为两种情况来讨论:
1. lambda表达式可以访问到所在的类中定义的变量(filed),也可以修改这个变量。
2. lambda表达式可以访问到外层代码块(enclosing scope)中定义的本地变量(local varable),但不能修改他们,并且,如果一个本地变量在lambda表达式中被读取的话,这个变量必须是final或按final的性质使用(final变量赋值以后就不能再任何地方再修改了)。
看下面的例子:

public class App {
    private int filed= 10;

    void method1() {
        int varable = 10;
        MyInterface myInterface = n -> {
            filed += 2;  //可读取,可修改
            int m = varable;  //可读取
            //varable += 2;  //不可修改
            return 1;
        };
        //varable += 2;    //已经在lambda表达式中被读取了,就是final了,不能被修改。
    }
}

在本例中,varable是一个本地变量,在lambda表达式中只能被读取而不能被修改,并且,一旦这个变量在lambda表达式中被读取了,那么在任何地方就不能被修改了。


方法引用
lambda表达式的本质是一个匿名方法,但如果有一个方法的签名(参数列表和返回值)和functional interface的签名一样并且逻辑正好是你需要的,那么你可以使用方法引用的方式来将它赋值给你的functional interface,而无需再编写lambda表达式。方法引用是jdk1.8中被引入的新语法,它跟lambda表达式息息相关,从字面意思来看,方法引用指向一个方法,但不调用它。其实这个特性在很多编程语言中都已经支持了,java也终于支持了。像其它编程语言一样,加括号就是调用方法,不加括号就是引用方法。
方法引用可以引用四种类型的方法,分别是:静态方法,实例方法,泛型方法,构造方法,引种每种方法的语法有略有区别。下面分别看个例子。下面这个类包含三个方法,对应前三种类型:

public class MyClass {

    public int instanceMethod(int number) {
        return number * 2;
    }

    public static int staticMethod(int number) {
        return number * 2;
    }

    public <t number="" extends=""> int genericMethod(T param) {
        return param.intValue() * 2;
    }

}

方法引用的操作符是两个冒号(::),这也是一个新的操作符。

引用静态方法
引用静态方法的语法是ClassName::methodName

myInterface = MyClass::staticMethod;
myInterface.run(5);

引用实例方法
应用实例方法的语法是instance::methodName

MyClass myClass = new MyClass();
myInterface = myClass::instanceMethod;
myInterface.run(5);

应用泛型方法

MyClass myClass = new MyClass();
myInterface = myClass::<integer>genericMethod;
myInterface.run(5);</integer>

引用构造方法
引用构造方法的语法是ClassName::new构造方法的返回值是它所在的类的类型。下面编写一个functional interface和一个构造函数。先来一个类和它的构造函数

public class Foo {
    String msg1, msg2;

    public Foo(String msg1, String msg2) {
        this.msg1 = msg1;
        this.msg2 = msg2;
    }
}

在来一个functional interface

interface FooInterface {
    Foo fooMethod(String m1, String m2);
}

这个里面的fooMethod的返回值是Foo,参数列表是两个String对象,与Foo类的构造函数的签名一致。下面是引用这个构造方法的方式

FooInterface fooInterface = Foo::new;
Foo fooObj = fooInterface.fooMethod("hello", "world");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值