> 文档中心 > 一直想弃用,从未被替代的Java8——入门篇(文字+代码对比讲解)

一直想弃用,从未被替代的Java8——入门篇(文字+代码对比讲解)

在这里插入图片描述

说在前面:
众所周知,JDK8 已经不算新了,甚至已经步入“老年代”了,但我们不可否认的是,目前大多数企业还在使用这个jdk版本。后面的工作中,小名可能会应用到它,之前也有所了解,前段时间正好得空,有机会系统的梳理一下相关知识点。 文章将分为两部分:
第一部分,小名将带大家简单了解一下JDK8中一些关于lambda的知识; 第二部分,小名将通过 Stream 特性写一些例子;
第三部分,小名将应用 Stream API 写一些例子。
希望可以对大家有所帮助

闲言少叙,正文开始:


系列文章导航:

  1. 入门篇
  2. Stream篇
  3. StreamAPI篇

持续更新中……


文章目录

        • 一、为什么要用lambda表达式
        • 二、lambda表达式的语法
          • 类型推断
        • 三、函数式接口
        • 四、方法引用
        • 五、变量作用域
        • 六、接口中的默认方法
        • 七、接口中的静态方法

一、为什么要用lambda表达式

  1. Lambda 允许将函数作为一个方法的参数传递进方法中。
  2. 使用 Lambda 表达式可以使代码变的更加简洁紧凑。

二、lambda表达式的语法

Lambda 表达式在Java 语言中引入一个操作符 -> 它将 Lambda 分为两个部分:
左侧:指定了 Lambda 表达式所需要的参数(参数列表)。
右侧:指定了 Lambda 体,即 Lambda 表达式要执行的功能(方法体)。

语法格式一: 无参数,无返回值

Runnable runnable = () -> System.out.println("语法格式一:无参数,无返回值");runnable.run();

语法格式二: Lambda 表达式的参数列表的数据类型可以省略不写(因为JVM编译器通过上下文推断出,数据类型,即“类型推断”)

List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5, 6, 7);System.out.println("↓【一般写法】↓");ints.forEach((Integer x) -> System.out.println(x));System.out.println("↓【类型推断】↓");ints.forEach((x) -> System.out.println(x));
类型推断

Lambda 表达式的类型是依赖于上下文环境由编译器推断出来的,通过推理算法确定参数的类型,如果可用,则确定结果被分配或返回的类型。所以,无需指定类型,程序依然可以编译。

语法格式三: 有一个参数,并且无返回值

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7);integers.forEach((x) -> System.out.println(x));

语法格式四: 若只有一个参数,小括号可以省略不写

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7);integers.forEach(x -> System.out.println(x));

语法格式五: 有两个以上的参数且有返回值,Lambda 体中若只有一条语句, return 可以省略不写

List<Integer> nums1 = Arrays.asList(12829, 298, 45333, 45454, 5457, 4536, 54147);System.out.println("排序前" + nums1);Comparator<Integer> com = (x, y) -> Integer.compare(x, y);Collections.sort(nums1, com);System.out.println("排序后" + nums1);

语法格式六: 有两个以上的参数且有返回值,Lambda 体中有多条语句要使用{}(花括号)包裹方法体

List<Integer> nums2 = Arrays.asList(13829, 8598, 51623, 68254, 4847, 6236, 68147);System.out.println("排序前" + nums2);Comparator<Integer> com2 = (x, y) -> {    System.out.print("x=" + x + " , " + "y=" + y);    System.out.println();    return Integer.compare(x, y);};Collections.sort(nums2, com2);System.out.println("排序后" + nums2);

三、函数式接口

  1. 有且只有一个抽象方法的接口被称为函数式接口。
  2. 函数式接口可以被隐式转换为 lambda 表达式。
  3. 函数式接口需要添加@FunctionalInterface注解,这样做它将被检查为一个函数式接口。
//函数式接口@FunctionalInterfacepublic interface MyFun<T> {    public T getValue(T t);}
public class UpWord {    public String toUpperString(MyFun<String> mf, String str) { String value = mf.getValue(str); return value;    }    @Test    public void test1() { //函数式接口的实现 String str = toUpperString((s) -> s.toUpperCase(), "abcdefg"); System.out.println(str);    }}

四、方法引用

创建Student实体类

public class Student {    private String name;    private int score;    /     * 无参 构造方法     */    public Student() {    }    /     * 有参 构造方法     */    public Student(String name, int score) { this.name = name; this.score = score;    }    /     * 创建 Student的静态方法     *     * @param supplier     * @return     */    public static Student create(final Supplier<Student> supplier) { return supplier.get();    }    /     * 输出 Student的静态方法(类方法)     *     * @param stu     */    public static void getStu(final Student stu) { System.out.println("Student " + stu.toString());    }    /     * 用于 类 调用输出Student的实例方法     */    public void getStuForClass() { System.out.println("Student " + this.toString());    }    /     * 用于 对象 调用输出Student的实例方法     */    public void getStuForObject(final Student student) { System.out.println("Student " + student.toString());    }   // 省略 set、get、toString 方法...}
  1. 类名::构造方法
Student student = Student.create(Student::new);
  1. 类名::静态方法
List<Student> students = Arrays.asList(student);students.forEach(Student::getStu);
  1. 类名::实例方法
students.forEach(Student::getStuForClass);
  1. 对象::实例方法
Student stu = new Student();students.forEach(stu::getStuForObject);

本小节示例仿照菜鸟教程编写

五、变量作用域

因为 Java 8 的 lambda 表达式其实是函数接口的内联实现,也就是匿名内部类,因此,可以引用任何外部的变量或者常量。

首先,定义一个公用的final修饰的变量和一个公用接口:

final String test = "Hello";interface lambdaInterface {    void getMessage(String message);}
  1. lambda 表达式可以使用外部 final 变量
@Testpublic void lambdaScope1() {    lambdaInterface li = msg -> System.out.println(test + msg);    li.getMessage(" World!");}
  1. lambda 可以(在作用域内外同理)引用普通的变量,但这个变量不能被二次赋值 (即隐性的具有 final 的语义)
@Testpublic void lambdaScope1() {    lambdaInterface li = msg -> System.out.println(test + msg);    li.getMessage(" World!");}

若是在作用域中,对变量二次赋值,则打破了隐性 final 的修饰(JDK8可以不用final修饰), 就会出现编译时报错
在这里插入图片描述

六、接口中的默认方法

Java8之前,Java中的接口不能有非抽象方法,并且实现接口的类必须为接口中定义的 每 个 方 法 提供一个实现,一旦向此接口中加入新的方法,就会导致所有的实现类必须实现新增方法,从Java8开始,接口支持两种新类型的方法及其实现。

接口支持的第一种新类型:默 认 方 法 ,通过default关键字标识,并且向接口提供非抽象方法的默认实现,实现接口的类如果不显式地提供该方法的具体实现,就会自动继承默认的实现。

ublic class defaultMethodTest {    interface lambdaInterface { String getMessage(String message); default double pow(int num) {     return Math.pow(num,2); }    }    @Test    public void test() { lambdaInterface lambdaInterface = new lambdaInterface() {     @Override     public String getMessage(String message) {  return message;     } }; System.out.println(lambdaInterface.getMessage("Hello")); System.out.println(lambdaInterface.pow(50));    }}

七、接口中的静态方法

接口支持的第二种新类型:静 态 方 法,通过static关键字标识,表示这个方法可以通过接口直接调用。

public class staticMethodTest {    public interface lambdaInterface { static void show(){     System.out.println("接口中的静态方法"); }    }    @Test    public void test(){ lambdaInterface.show();    }}

如若您在文章中发现任何错误的地方,希望您可以在评论区给予小名批评指正🤝 如果觉得小名的文章帮助到了您,请关注小名的专栏【Java8】,支持一下小名😄,给小名的文章点赞👍、评论✍、收藏🤞谢谢大家啦~♥♥♥

一直想弃用,从未被替代的Java8——入门篇(文字+代码对比讲解) 创作打卡挑战赛 一直想弃用,从未被替代的Java8——入门篇(文字+代码对比讲解) 赢取流量/现金/CSDN周边激励大奖