常见面试题:java8有什么新特性?
常见面试题:java8有什么新特性?
主要有以下这些新特性:
lambda 表达式,经常配合函数式接口使用,可以有效减少代码量
Runnable 是一个函数式接口,下面展示了创建线程三种写法,显然最后一种最简洁:
class OldWay implements Runnable {
@Override
public void run() {
System.out.println("最原始的方法");
}
} public class Test {
public static void main(String[] args) { new Thread(new OldWay()).start(); new Thread(new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类");
}
}).start(); new Thread(() -> {
System.out.println("lambda表达式");
}).start(); }
}
在 new 一个 Thread 时需要传入一个 Runnable 接口的实现类
- 第一种是最原始的做法,先创建一个 class 来实现 Runnable 接口,然后在创建线程时传入这个实现类,太麻烦了
- 第二种是匿名内部类的写法,把实现类的名字给省略掉了,稍微方便点,但
run这个方法名其实也有点冗余,因为 Runnable 里面就这么一个方法,不写出来应该也没关系啊 - 第三种是 lambda 表达式的写法,把方法名也省略掉了,最简洁,但注意,如果接口里有多个方法,那么只能采用前两种方法了
更直观的感受一下 lambda 表达式和函数式接口之间的关系:
public class Test {
public static void main(String[] args) {
Runnable runnable = () -> {
System.out.println("nb");
};
}
}
另一个常见应用就是集合类的
forEach方法,需要一个Consumer参数,这也是一个函数式接口,里面的accept方法需要一个参数并且没有返回值(不用记,在 IDEA 里点进去看就行),一个例子如下,它遍历 list 中的每个元素,加一后输出:public class Test {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
//2 3 4
list.forEach((Integer num) -> {
num = num + 1;
System.out.println(num);
});
}
}
lambda 表达式还有些小细节,比如参数列表中参数的类型其实可以省略,如果代码块里只有一条语句那么花括号也可以省略,如果参数列表里只有一个参数那么圆括号也可以省略,但其实就算不省略也足够简洁了,我觉得没必要省略
方法引用,感觉有点说不清,可以看个例子,就比如前面遍历 list,如果我就是想遍历一次 list 然后输出,可以用到方法引用:
public class Test {
public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3); list.forEach((Integer num) -> {
System.out.println(num);
}); list.forEach(System.out::println); }
}
首先,
forEach是需要一个Consumer参数的,这个函数式接口的accept方法需要一个参数并且没有返回值,我们有两个方案,一个就是自己写一个 lambda 表达式,另一个就是使用方法引用,直接引用一个已经写好了的满足条件的方法,比如这里的System.out.println方法就是需要一个参数的void方法,满足条件,当然我们也可以定制一个满足条件的方法然后用方法引用的方式来使用,如下:class TestReference{
public static void myPrint(Integer num){
System.out.println(num);
}
}
public class Test {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.forEach(TestReference::myPrint);
}
}
函数式接口,前面其实已经提到过了,如果一个接口里面只有一个方法,那么这就是一个函数式接口,对于函数式接口,我们可以通过 lambda 表达式或者方法引用来进行快速的实现,而不必新建一个 class 去继承或者写一个匿名内部类
默认方法,意思是说,我们在写一个接口时可以通过
default关键字为其中的方法提供默认的实现方案,使得实现类就算不覆写这个方法也没有关系:interface TestInterface{
default void test(){
System.out.println("here");
}
} class TestDefault implements TestInterface{
//没有覆写test方法也没有报错
} public class Test {
public static void main(String[] args) {
//here
new TestDefault().test();
}
}
Stream API,我们可以把一个集合转换为流,在这个流上做各种操作,比如查找、排序、过滤等等
主要有以下这些操作:

- 中间操作:指操作完成后还是返回一个流对象,可以拿着这个对象继续操作下去
- 结束操作:指操作完成后不再返回流对象,一切都结束了
- 无状态:指元素的处理不受之前元素的影响,可以挨个处理
- 有状态:指该操作只有拿到所有元素之后才能继续下去
- 非短路操作:指必须处理完所有元素才能得到最终结果
- 短路操作:指遇到某些符合条件的元素就可以得到最终结果
来个案例,现在给定一个 list,想要先求出每个元素的平方,然后排序,然后找出 10 和 100 之间的那些元素,然后去除重复元素,最后输出:
public class Test {
public static void main(String[] args) {
//准备我们的list
ArrayList<Integer> list = new ArrayList<>();
int[] ints = {4, 1, 6, 2, 8, 5, 15, 11, 9};
for (int i : ints) {
list.add(i);
}
//转换为流
Stream<Integer> stream = list.stream();
//第一步,求出每个元素的平方
stream.map((Integer origin) -> {
return origin * origin;
})
//第二步,排序
.sorted()
//第三步,找出10和100之间的那些值
.filter((Integer num) -> {
return num >= 10 && num <= 100;
})
//第四步,去重
.distinct()
//第五步,输出
.forEach(System.out::println);
}
}
从案例中可以发现,很多流操作是需要一个函数式接口作为参数的,因此一定要搭配前面的 lambda 表达式和方法引用来完成这些流操作,否则代码量是过大的
至于到底需要写什么样的 lambda 表达式(几个参数,返回值是什么),一定要在 IDEA 里点进去看,直接背是不现实的
新的 Date Time API,因为 java 中同时存在
java.util.Date和java.sql.Date两个时间类,很容易让人迷惑,而且这两个包里的内容也存在诸多问题,因此 java8 中新增了java.time这个包来把所有时间类的 API 一网打尽直接看个案例吧,演示部分 API 的使用:
public class Test {
public static void main(String[] args) { //获取当前的日期时间(年月日+时分秒)
LocalDateTime currentTime = LocalDateTime.now();
System.out.println("当前的日期和时间: " + currentTime); //获取当前的日期(年月日)
LocalDate date1 = currentTime.toLocalDate();
System.out.println("date1: " + date1); //分别得到当前的月、日、秒
Month month = currentTime.getMonth();
int day = currentTime.getDayOfMonth();
int seconds = currentTime.getSecond();
System.out.println("月: " + month +", 日: " + day +", 秒: " + seconds); //把当前的日期时间中的年替换为2012,日替换为10
LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);
System.out.println("date2: " + date2); //显式的构造出一个日期
LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12);
System.out.println("date3: " + date3); //显式的构造出一个时间
LocalTime date4 = LocalTime.of(22, 15);
System.out.println("date4: " + date4); //解析字符串来得到一个时间
LocalTime date5 = LocalTime.parse("20:15:30");
System.out.println("date5: " + date5);
}
}
最后的输出如下:
当前的日期和时间: 2021-08-24T22:03:43.468015700
date1: 2021-08-24
月: AUGUST, 日: 24, 秒: 43
date2: 2012-08-10T22:03:43.468015700
date3: 2014-12-12
date4: 22:15
date5: 20:15:30
Optional 类,很好的解决了
NullPointerException的问题
学习过程中,部分内容有参考网上其它人的文章,如有侵权必删
常见面试题:java8有什么新特性?的更多相关文章
- java常见面试题及答案 1-10(基础篇)
java常见面试题及答案 1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被 ...
- java常见面试题及答案
java常见面试题及答案 来源 https://blog.csdn.net/hsk256/article/details/49052293 来源 https://blog.csdn.net/hsk25 ...
- 【搞定 Java 并发面试】面试最常问的 Java 并发进阶常见面试题总结!
本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.觉得内容不错 ...
- iOS常见面试题汇总
iOS常见面试题汇总 1. 什么是 ARC? (ARC 是为了解决什么问题而诞生的?) ARC 是 Automatic Reference Counting 的缩写, 即自动引用计数. 这是苹果在 i ...
- Java 常见面试题(一)
1)什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件.Java被设 ...
- 【javascript常见面试题】常见前端面试题及答案
转自:http://www.cnblogs.com/syfwhu/p/4434132.html 前言 本文是在GitHub上看到一个大牛总结的前端常见面试题,很多问题问的都很好,很经典.很有代表性.上 ...
- Vue常见面试题汇总
Vue框架常见面试题 1.active-class是哪个组件的属性?嵌套路由怎么定义? 答:vue-router模块的router-link组件. 2.怎么定义vue-router的动态路由?怎么 ...
- 夯实Java基础系列16:一文读懂Java IO流和常见面试题
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- redis知识点及常见面试题
redis知识点及常见面试题 参考: https://zm8.sm-tc.cn/?src=l4uLj4zF0NCIiIjRnJGdk5CYjNGckJLQrIqNiZaJnpOWjIvQno2Llpy ...
随机推荐
- Echarts快速入门---------v客学院技术分享
ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等) ...
- 分别在Update和FixedUpdate使用GetKeyDown
测试目的 探究分别在Update和FixedUpdate使用GetKeyDown执行次数,会不同的 测试开始 在Update测试 我们先在Update测试,很正常是一帧重置一下状态,以防止点击一下执行 ...
- Python urllib翻译笔记一
22.5.urllib- URL处理模块urllib 是一个收集几个模块以处理URL的包: urllib.request 用于打开和阅读URL urllib.error 包含由urllib.reque ...
- 第三篇--如何修改exe文件版本号和文件信息
控制台程序添加版本信息方法: 项目右键 Add-->Resource-->选择Version-->new,然后就可以修改里面的信息了,重新编译一下就OK.
- 利用swagger和API Version实现api版本控制
场景: 在利用.net core进行api接口开发时,经常会因为需求,要开发实现统一功能的多版本的接口.比如版本V1是给之前用户使用,然后新用户有新需求,这时候可以单独给这个用户写接口,也可以在V1基 ...
- DC-8靶机
仅供个人娱乐 靶机信息 下载地址:http://www.five86.com/downloads/DC-8.zip 一.主机扫描 二.信息收集 http://192.168.17.135/robots ...
- JAVAWEB - Servlet原理及其使用>从零开始学JAVA系列
目录 Servlet原理及其使用 什么是Servlet Servlet的使用 编写一个Servlet,使用继承HttpServlet的方式 配置web.xml 很简单的几个JSP文件 小提示,如果继承 ...
- HttpRunner3源码阅读:7.响应后处理 response.py
response 上一篇说的client.py来发送请求,这里就来看另一个response.py,该文件主要是完成测试断言方法 可用资料 jmespath[json数据取值处理]: https://g ...
- 科普—为什么要用ECDSA加签及其数学上的验签证明
在上文介绍了ECDSA算法流程及模块划分,为了帮助一些小白弄懂啥是ECDSA,特此开一篇科普博文. 一.首先为啥要进行数字签名? 假设Alice要将一份合同m传输给Bob,合同上附有Alice的电子纸 ...
- Nat Comm | 中科院动物所张勇团队合作揭示动物中DNA转座子介导基因重复的机制
1950年Barbara Mclintock 首次在玉米中发现转座子(TEs),并由此获得诺贝尔奖.尽管长期被认为是垃圾DNA,但现在TEs被广泛认可是宿主基因组演化的重要推动力.它们可引起包含基因重 ...