常见面试题: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.Datejava.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有什么新特性?的更多相关文章

  1. java常见面试题及答案 1-10(基础篇)

    java常见面试题及答案 1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被 ...

  2. java常见面试题及答案

    java常见面试题及答案 来源 https://blog.csdn.net/hsk256/article/details/49052293 来源 https://blog.csdn.net/hsk25 ...

  3. 【搞定 Java 并发面试】面试最常问的 Java 并发进阶常见面试题总结!

    本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.觉得内容不错 ...

  4. iOS常见面试题汇总

    iOS常见面试题汇总 1. 什么是 ARC? (ARC 是为了解决什么问题而诞生的?) ARC 是 Automatic Reference Counting 的缩写, 即自动引用计数. 这是苹果在 i ...

  5. Java 常见面试题(一)

    1)什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件.Java被设 ...

  6. 【javascript常见面试题】常见前端面试题及答案

    转自:http://www.cnblogs.com/syfwhu/p/4434132.html 前言 本文是在GitHub上看到一个大牛总结的前端常见面试题,很多问题问的都很好,很经典.很有代表性.上 ...

  7. Vue常见面试题汇总

    Vue框架常见面试题   1.active-class是哪个组件的属性?嵌套路由怎么定义? 答:vue-router模块的router-link组件. 2.怎么定义vue-router的动态路由?怎么 ...

  8. 夯实Java基础系列16:一文读懂Java IO流和常见面试题

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  9. redis知识点及常见面试题

    redis知识点及常见面试题 参考: https://zm8.sm-tc.cn/?src=l4uLj4zF0NCIiIjRnJGdk5CYjNGckJLQrIqNiZaJnpOWjIvQno2Llpy ...

随机推荐

  1. robotframework - PO设计

    1.添加新建好的资源 2.测试用例原始代码如下(未做任何分离的数据) *** Settings ***Library SeleniumLibraryResource UI分层一.txtResource ...

  2. 开源百宝箱《HelloGitHub》第 64 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. HelloGitHub 有实战.教程.黑科技.开源书籍.企业级开源项目,涵盖多种编程 ...

  3. POJ1417 True Liars 题解

    通过读题,容易发现,当回答为yes时 \(x,y\) 必属于同类,当回答为no时二者必为异类(并且当 \(x=y\) 时,回答必为yes,不过这题不用这个性质). 于是先按关系维护连通块,然后求出每个 ...

  4. Floyd弗洛伊德算法

    先看懂如何使用 用Java实现一个地铁票价计算程序 String station = "A1 A2 A3 A4 A5 A6 A7 A8 A9 T1 A10 A11 A12 A13 T2 A1 ...

  5. windows 10家庭版安装SQL Server 2014出现.net 3.5失败问题解决。

    在安装SQL Server 2014的过程中,出现.net 3.5缺失,导致失败问题. 后来,研究了下,解决思路如下: 先将电脑更新到了windows 10专业版,(因为需要用到专业版才有的组策略管理 ...

  6. QT常用控件(三)——自定义控件封装

    引言 Qt已经提供了很多的基础控件供开发使用,而Qt原生的控件有时候并不能满足我们的需求,特别是在工业的运用上,比如我们需要一个日期时间的选择器,Qt虽然已经提供了原生的QDateTime控件,但这个 ...

  7. 实战 | Hive 数据倾斜问题定位排查及解决

    Hive 数据倾斜怎么发现,怎么定位,怎么解决 多数介绍数据倾斜的文章都是以大篇幅的理论为主,并没有给出具体的数据倾斜案例.当工作中遇到了倾斜问题,这些理论很难直接应用,导致我们面对倾斜时还是不知所措 ...

  8. 为ScrollView增加圆角的三种方式,及自定义属性【在Linearlayout中新增ScrollView支持滚动 后续】

    获取圆角的几种方案如下:方案一:通过shape来实现,给scrollView增加背景来实现方案二:通过自定义ScrollView,还要自定义属性,在dispatchDraw中不停的裁剪方案三:用And ...

  9. DNS反向解析,主从服务器,分离解析(内外网)

    目录 实验一:DNS反向解析 1.安装bind 2.查找配置文件路径 3.配置/etc/named.conf主配置文件 4.修改/etc/named.rfc1912.zones区域配置文件(复制两个) ...

  10. C++ //继承同名静态成员处理方式

    1 //继承同名静态成员处理方式 2 #include <iostream> 3 #include <string> 4 using namespace std; 5 6 cl ...