常见面试题: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. 如何掌握C#的核心技术

    如何掌握C#的核心技术 感谢网友毛大神制作的图. 引子 前不久看到一个段子,某年宁波交警引进人脸识别技术抓拍行人闯红灯,结果一天下来被发现闯红灯次数最多的是珠海女子董小姐,日闯红灯3000多次.宁波交 ...

  2. Linux用户提权管理方案

    提权管理方案背景: 如果一个公司有10余个运维或网络安全人员,同时管理服务器,切换到管理员用户时(su - root),必须要有root管理员密码,如果其中一人修改过root密码,其他用户则登录不了, ...

  3. 【模拟】选数 luogu-1037

    AC代码 #include <bits/stdc++.h> using namespace std; #define ms(a,b) memset(a,b,sizeof(a)) typed ...

  4. 注解@ConfigurationProperties使用方法(二十)

    前言 最近在思考使用java config的方式进行配置,java config是指基于java配置的spring.传统的Spring一般都是基本xml配置的,后来spring3.0新增了许多java ...

  5. GraphPad Prism 9.0安装破解教程

    graphpad prism 9.0是一款强大的科学软件,拥有大量分析图表,prism是回归分析的著名软件之一,非常适用于科研生物医学等领域.本文提供其破解版,激活码,序列号,破解教程等,可以完美激活 ...

  6. No_1 手写Proxy

    手写动态代理主要原理: userDAO=(UserDAO)Proxy.newProxyinstance(classloader,interfaces[],new MyInvocationHandler ...

  7. 关于intouch/ifix嵌入视频控件并使用(海康,大华)

    2017年下半年项目开始接触利用intouch工控软件来进行项目二次开发.其中关于驱动的问题始终是上位机的重中之重,暂且不表(嘿嘿--),首先遇到的问题就是在弹窗中嵌入视频控件,监控设备的开停状态.经 ...

  8. wdlinux一键安装包

    下载安装(ssh登录服务器,执行如下操作即可,需要用到root用户权限来安装) v3版本已经发布,更多可看论坛 wdCP v3版本讨论区 更多安装请看 http://www.wdlinux.cn/bb ...

  9. Resnet网络详细结构(针对Cifar10)

    Resnet网络详细结构(针对Cifar10) 结构 具体结构(Pytorch) conv1 (conv1): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, ...

  10. vue日记之可展开的消息气泡

    项目小需求之聊天气泡可展开内容 因为某些信息内容太长或者某种原因必须分行输出,这就导致了有时候一个气泡占据了一整个聊天区域 所以我打算实现一个在该气泡加载的时候判断其气泡长度,并在长度过长的情况下进行 ...