常见面试题: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. 拿来-util工具函数

    记录一些写的好的工具函数.以便学习和项目中直接拿来使用. 判断值是否相等:使用于任何数据类型:基本数据类型和复杂深层次对象 function deepEqual (a, b) { if (a === ...

  2. python+selenium+unittest发送Mail163邮件(PO)

    一.如下为项目的目录分布: 二.数据驱动yaml 三.Mail163登录测试用例编写 四.163邮件配置 五.Mail163测试用例执行: 六.邮件执行情况如下:

  3. 在Java中,负数的绝对值竟然不一定是正数!!!

    绝对值是指一个数在数轴上所对应点到原点的距离,所以,在数学领域,正数的绝对值是这个数本身,负数的绝对值应该是他的相反数. 这几乎是每个人都知道的. 在Java中,想要获得有个数字的绝对值,可以使用ja ...

  4. 在docker for windows建立mssql容器后,ssms连接mssql出现错误号码18456的问题

    在docker for windows建立mssql容器后,ssms连接mssql出现错误号码18456的问题 笔者提供一个可能会没考虑到的点. 请检查本机是否安装了mssql!!! 请检查本机的ms ...

  5. 在LinuxMint 17 MATE中安装NVIDIA显卡驱动

    第一步:在Linux系统中安装Nvidia显卡驱动需要关闭X Server. 打开终端,进入ROOT权限,执行以下命令 $ sudo service mdm stop 此时将会把X Server关闭, ...

  6. 15Java进阶 进程

    1 线程控制 t.join():让主线程进入线程池,等待t执行完才执行. t.sleep():让线程阻塞,休眠一段时间,休眠结束后进入就绪状态.不会释放锁. t.yield():让线程让出CPU,从运 ...

  7. create-react-app 项目安装less

    1.安装依赖: npm install less less-loader --save-dev 2.在webpack.config.js里面添加配置:(若webpack.config.js文件没有显示 ...

  8. 破解网站码验证,Java实现,不调用任何平台api接口

    package image.images; import java.io.File; import java.io.IOException; import java.io.InputStream; i ...

  9. leetcode最短无序连续子数组

    平民解法: 既然是找最小数组,那就得到一个排序好的数组,然后直接和初试数组比对,用一个left,right分别记录从最初开始不同,到最后不同的小标,最后左右做差再加一,就能得到长度. 其他解法: 双指 ...

  10. Java方法02——定义与调用

    方法的定义与调用 定义与调用 例子  package method; ​ public class Demon03 {     public static void main(String[] arg ...