Lambda表达式

jdk8更新了一个新特性,Lambda表达式,它采用了一种简洁的语法定义代码块,取代了大部分的匿名内部类,主要用内部类完成实现接口。

这里给出一系列接口,供上下文操作

public interface Comparator{
    int compare(T a, T b);
}
public interface ReturnNum {
    int getNum(int a);
}

使用lambda表达式对接口的要求,接口中只有一个 抽象方法。注意,是 抽象方法。

lambda表达式由:参数,箭头(->),及一个表态式组成。表达式中可以像写方法一样,把代码放在{}中

lambda表达式: InterFaceType var = () -> {};
例:返回最大数 Comparator com = (int num1, int num2) -> { return (num1 > num2 ? num1 : num2) }

public class Test{
    public static void main(String[] args){
        Comparator comstr = (first,second) -> first.length() - second.length();
        System.out.println(comstr.compare("String", "name"));
    }
}
/*
2

Process finished with exit code 0
*/

1.如果想把现成的方法代码传递给实现接口的匿名内部类的方法。语法: object::method

主要分3种情况 object :: instanceMethod — 通过对象引用提供方法 Class :: staticMethod — 通过类名提供方法 Class :: instanceMethod — 通过类名提供方法,不同的是如果参数是多个,那第一个参数会去调用与这个方法同名的方法,传递的的是后面的参数,如 String::compareTolgnoreCase等同 (x,y) -> x.compareTolgnoreCase(y)
如果存在重载方法,编译器会根据接口中方法声明的参数列表来匹配对应的。

public class Test{
    public static void main(String[] args){
        //通过类名把static方法传递给匿名内部类的方法
        ReturnNum retnum1 = Test::getNUmAddOne;
        System.out.println(retnum1.getNum(4));//5

        //通过对象把普通方法传递给匿名内部类的方法
         ReturnNum retnum2 = new Test()::getNumAddTwo;
        System.out.println(retnum2.getNum(4));//6
    }
    public static int getNumAddOne(int num){
        return num+1;
    }
    public int getNumAddTwo(int num){
        return num+2;
    }
}

2.把构造器引用传递给接口中对象生成器的方法。语法: ClassType::new

ClassType::new — ClassType代表要获取那个类的构造器
其等同于 () -> new ClassType()

interface ItemCreatorBlankConstruct{
    Item getItem();//获取Item的无参构造,如果要获取有参构造,只需在参数列表声明对应的参数
}
public static void main(String[] args){
    ItemCreatorBlankConstruct getconstruct = Item::new;
    Item blankItem = getconstruct.getItem();
}

3.作用域

如果lambda表达式要调用外围变量,要确保这个引用值不会改变,也就是要确保这个变量是最终变量(final)。

public static void countDown(int start, int delay){
    ActionListener listener = event -> {
        start--;//编译报错,start是外围变量,lambda不能引用不是最终状态的外围变量
        System.out.print(strart);//在lambda表达式中使用的变量应该是最终的或有效的最终的。
    };
    new Timer(delay, listener).start();
}
int num = 10;
ActionListener listener = e -> {
    System.out.println(num);//编译报错,num变量在下文中发生改变,lambda不能引用不是最终状态的外围变量
};
num++;

在lambda中不能声明与局部变量同名的参数或变量

public static void countDown(int start, int delay){
    ActionListener listener = event -> {
        int start = 10;//编译报错
        System.out.print(strart);
    };
}

在lambda中使用 this代表的是当前类的引用

public class Test{
    public static void countDown(int start, int delay){
    ActionListener listener = event -> {
        System.out.println(this.toString());//this代表当前类Test的引用
    };
}
}

使用场景

1.通过匿名内部类重写Thread类的run方法

Thread thread = new Thread(() -> {
    System.out.println("new Thread1");
});
thread.start();

2.对集合遍历

ArrayList list = new ArrayList();
list.add(5);
list.add(4);
list.add(3);
list.add(2);
/*
ArrayList类中的forEach方法接收的是一个Consumer 接口参数
Consumer是jdk提供的函数式接口
*/
list.forEach(num -> System.out.println(num));//list.forEach(System.out::println)

函数式接口

有且仅有一个抽象方法的接口,这样的接口被称为函数式接口(JDK1.8),当需要对这种接口创建对象时,可以用lambda表达式。

函数式接口是JDK1.8更新的内容,在JDK1.8中接口还可以声明非抽象的方法。只有用default修饰的方法才能在接口中有方法体

interface DomeInt{
    int getInteger();
    default void to(){ //code }
}

为了让接口明确的被定义成函数式接口,我们要在声明接口时添加 注释@FunctionalInterface,这样我们在函数式接口中添加第二个抽象方法时,编译器就会报错

@FunctionalInterface//Error : Multiple non-overriding abstract methods found in interface Lambda.ReturnOneParam
public interface ReturnOneParam {
    int getNum(int num);
    void outNum();
    default void to(){}
}

Original: https://www.cnblogs.com/hello12153-java/p/15981109.html
Author: hello_12153_98
Title: Lambda表达式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/570479/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球