读书笔记--《写给大忙人的JavaSE 9 核心技术》—第3章

接口和lambda表达式

接口

它可以让你在不提供实现的情况下,指定应该做什么。(主要在设计阶段用得到)

示例代码

public interface Test1 {
    // 接口中的方法默认为public
    public void saySomething(String something);
    // 在接口中可以定义静态方法
    // 静态方法只能由这个接口去调用,
    // 实现此接口的对象是不能调用的。
    static void sayMyName(){
        System.out.println("my name is Test1");
    }
    // 在接口中可以定义默认方法,实现此接口的类可以重新
    // 默认方法结束了这种经典模式——提供一个接口和实现该接口大多数或全部方法的伴随类
    default void sayHello(){
        System.out.println("Hello");
    }
}

lambda

参考博文1

参考博文2

这个lambda 表达式 和 JavaScript里面的箭头函数很像

其核心是一种简写方式,可以取代大部分的匿名内部类,写出更优雅的 Java 代码。

 // 一行语句
 (String s1,String s2) -> s1.length() - s2.length()
 
 // 多行语句
  (String s1,String s2) ->{
      if(s1.length()>s2.length()){
          return "yes"
      }else{
          return "no"
      }
  }
  
 // 无参数
 () -> return "666"
 
 // 如果参数类型可以推导出来,则可以省略。
 // 示例见下方代码

函数式接口

该接口只有一个抽象方法,该接口会被@FunctionalInterface这个注解所修饰

当你需要一个实现函数式接口的对象实例时,可以提供一个lambda表达式来创建。

import java.util.Arrays;
import java.util.Comparator;

public class Test3 {


    public int[] sort(int[] s) {
        //Arrays.sort(s);
        Integer[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
        Comparator myComparator = new MyComparator();
        //自动装包机制不能应用于数组。
        // 这里 Comparator<Integer>,是Integer,而数组是int类型。这两个不一样!
        // 要把int改为Integer
        // Arrays.sort(s ,myComparator); //会报错!

        //Arrays.sort(a, myComparator);

        // lambda 表达式简写
        Arrays.sort(a, (n1, n2) -> {
                    if (n1 > n2) {
                        return -1;
                    } else {
                        return 1;
                    }
                }
        );
        for (int n : a) {
            System.out.println(n);
        }
        return s;
    }


    class MyComparator implements Comparator<Integer> {
        @Override
        //返回正数,零,负数各代表大于,等于,小于
        public int compare(Integer o1, Integer o2) {
            if (o1 > o2) {
                return -1;
            } else {
                return 1;
            }
        }


    }
}

作用域

lambda表达式的方法体与嵌套代码有着相同的作用域。在lambda表达式中不允许声明一个与局部变量同名的参数或者局部变量。

// 错误
int first = 0;
Comparator<Integer> comp = (first,second)->first > second

this指向问题

lambda表达式中this指向创建lambda表达式的外部类。

这里的this指向App,而不是Runnable实例。 这一点和JavaScript中的箭头函数很像,this指向调用此函数的对象。

class App() {
    public void doWork(){
        Runnable runnable = ()->{
            System.out.println(this.toString());
        }
    }
}
lambda一般情况下会被编译成静态匿名方法,引用的外部变量以参数的方式传递。

如果 lambda 里使用了this 指标,则被编译为匿名内部方法,以让 this 指针指向lambda 外部类。

闭包

闭包就是能够读取其他函数内部变量的函数。

这个概念在JavaScript中相当重要

https://developer.mozilla.org...

在Java中有了lambda表达式,也有了闭包的概念,但是和JavaScript中的闭包有些不同。没有JavaScript中的强大。

import java.util.function.Consumer;
public class Main {
    public static void main(String[] args) {

        int num = 10;

        Consumer<String> consumer = ele -> {
            System.out.println(num);
        };

        //num = num + 2;
        consumer.accept("hello");
    }
}

如果把注释删掉,则会报错。因为在lambda表达式中只能引用那些值不会改变的变量。


灿若星空丶
7 声望1 粉丝

东华大学研究生