- 前言
- 今天我来聊聊 Java8 的一些新的特性,确实 Java8 的新特性的出现,给开发者带来了非常大的便利,可能刚刚开始的时候会有点不习惯的这种写法,但是,当你真正的熟悉了之后,你一定会爱上这些新的特性的,这篇文章就来聊聊这些新特性。
- lambda 表达式
- lambda 表达式在项目中也是用的到的,这种新的语法,大大的改善了以前的 Java 的代码,变得更加的简洁,我觉得这也是为什么 Java8 能够很快的流行起来的原因吧。
- 这里我们用几个以前的经典的 Java 的写法和用 lambda 表达式的方式进行对比。
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| System.out.println("这是使用匿名内部类的方式。。。"); |
| } |
| }).start(); |
| |
| |
| new Thread(() -> { |
| System.out.println("这是使用lambda表达式的方式。。。"); |
| }).start(); |
- 你会发现,用 lambda 表达式的方式能够写更少的代码,看起来也会更加的舒服和简洁。
- 这里没有使用参数,只是一个简单的例子。
- 我们再看一个例子, 遍历方式
| |
| List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); |
| for (int i : list) { |
| System.out.println(i); |
| } |
| |
| |
| Stream.of(1, 2, 3, 4, 5).forEach((x) -> { |
| System.out.println(x); |
| }); |
- 在原始的方式中,我们一般使用 foreach 的方式进行遍历,有了 Java8 的方式之后,我们可以用 forEach 方法,然后,再用 lambda 表达式的方式进行遍历,也让原来的方式变得更加的简洁。
- 在这个例子中,我们加了一个参数,在()中间我们加了一个 x ,代表的意思其实是:通过 forEach 方法,我们把一个元素已经赋值到 x 中了,拿到这个 x ,我们就可以输出结果。
- 总结
- lambda 的使用方式其实很简单,可以总结为下面的方法。
- ([参数可选,…]) -> {}
- 方法引用
- 方法引用其实是 lambda 表达式的部分的简化,也就是为了简化 lambda 表达式而存在的感觉,下面我们还讲讲怎么使用方法引用。
| |
| |
| |
| |
| |
| |
| |
| @Test |
| public void test_method_reference() { |
| |
| Stream.of("A", "BB", "CCC", "DDDD", "FFFFF") |
| .map(s -> s.length()) |
| .forEach((x) -> { |
| System.out.println(x); |
| }); |
| |
| |
| Stream.of("A", "BB", "CCC", "DDDD", "FFFFF") |
| .map(String::length) |
| .forEach((x) -> { |
| System.out.println(x); |
| }); |
| |
| |
| Stream.of( |
| new ClassMate("1", "蒋小晴"), |
| new ClassMate("2", "xiaoqing") |
| ).map(ClassMate::getName) |
| .forEach(x -> { |
| System.out.println(x); |
| }); |
| |
| } |
- 在第一个测试中,我们用的是 lambda 表达式来获取每个字符串的长度。
- 在第二个测试中,我们使用的是静态方法引用来获取每个字符串的长度。
- 在第三个测试中,我们使用的是实例方法引用。
- 解释
- ① map 方法是映射的意思。
- ② forEach 方式是遍历每一个元素。
- ③ ClassMate 是一个包含 id 和 name 的简单 po 类。
- 通过上面这个例子,基本上我们就知道怎么使用方法引用了。下面我们进行一个小的总结。
- 总结
- ① 使用方法 类名::方法名
- ② 方法可以是:静态方法,实例方法
- 构造函数引用
- 在上面我们讲了方法引用的基本使用方法,其实除了方法引用以外,还有构造函数引用,回想一下,以前我们创建对象是怎么做?是不是需要 new 一个对象呢,那么现在用构造函数引用又是怎么做的呢?
- 下面我们用一个例子讲解一下,在这个例子中,对象还是使用上面的 ClassMate。
| |
| |
| |
| |
| |
| |
| |
| @Test |
| public void test_method_reference2() { |
| |
| Stream.of("A", "BB", "CCC", "DDDD", "FFFFF") |
| .map(s -> new ClassMate(s)) |
| .collect(Collectors.toList()); |
| |
| |
| Stream.of("A", "BB", "CCC", "DDDD", "FFFFF") |
| .map(ClassMate::new) |
| .collect(Collectors.toList()); |
| } |
- ① 第一个我们使用的是 lambda 表达式进行创建对象的 s -> new ClassMate(s)。
- ② 第二个我们使用的是构造函数引用创建对象的 ClassMate::new 。
- ③ 我们发现构造函数引用:类名::new ,然后对于使用哪一个构造函数是由上下文决定的,比如有一个参数和两个参数和无参数的构造函数,会自动确定用哪一个。
- 接口
- 在 Java 8 之前的接口是不能有实现的,只能定义抽象方法,然而,在 Java 8 以后,增加了一个新的功能,可以添加实现,可以定义默认方法,可以定义静态方法。
- 函数式接口
- 什么是函数式接口呢?
- 这个名词在 Java 中以前是很少听到的,但是正是有了 Java 8 的横空出世,函数式编程也变得熟悉了。
- 在一个接口中我们以 @FunctionalInterface 注解声明一个接口,并且接口中只有一个抽象方法,那么我们就叫做这是一个函数式接口。
| |
| |
| |
| |
| |
| |
| |
| @FunctionalInterface |
| public interface FunctionalInterfaceTest { |
| |
| void test(String s); |
| } |
- ① 上面的接口中只有一个抽象方法,所以这是一个函数式接口。
- ② 如果上面接口中再加一个抽象方法,那么就不是函数式接口了。
- 下面,我们再通过继承来继承这个接口。
| |
| |
| |
| |
| |
| |
| |
| public interface FunctionalTest extends FunctionalInterfaceTest{ |
| |
| int test2(); |
| } |
- ① 我们继承了上面的接口,并且加了一个 test2 方法。
- ② 这里注意,如果一个接口集成现有的函数式接口后,又加了其他的抽象方法,这个接口就不是函数式接口了。
- 默认方法, 默认方法很简单,用 default 声明即可。
| |
| |
| |
| |
| |
| |
| |
| @FunctionalInterface |
| public interface FunctionalInterfaceTest { |
| |
| void test(String s); |
| |
| |
| default String getStr(){ |
| return null; |
| } |
| } |
- 静态方法
| |
| |
| |
| |
| |
| |
| |
| @FunctionalInterface |
| public interface FunctionalInterfaceTest { |
| |
| void test(String s); |
| |
| |
| static String getStr2(){ |
| return null; |
| } |
| |
| |
| default static String getStr3(){ |
| return null; |
| } |
| } |
- ① 实现的静态方法,用 static 声明。
- ② 注意不能同时使用 default 和 static 声明。
- 总结
- 在这篇文章中,我们讲了 lambda 表达式、方法引用、函数式接口、接口中的静态方法、接口中的默认方法的使用。
- 转载出处
- 转自 点击跳转, [不怕报错 就怕不报错的小猿猿]的博客
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~