Java 语言特性、版本特性及Map详解

157 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第31天,点击查看活动详情

1.Java 语言特性

image.png

  • Java 的集合类中部分需要重点了解类的实现。例如,HashMap、TreeMap 是如何实现的等。

  • 动态代理与反射是 Java 语言的特色,需要掌握动态代理与反射的使用场景,例如在 ORM 框架中会大量使用代理类。而 RPC 调用时会使用到反射机制调用实现类方法。

  • Java 基础数据类型也常常会在面试中被问到,例如各种数据类型占用多大的内存空间、数据类型的自动转型与强制转型、基础数据类型与 wrapper 数据类型的自动装箱与拆箱等。

  • Java 对对象的引用分为强引用、软引用、弱引用、虚引用四种,这些引用在 GC 时的处理策略不同,强引用不会被 GC 回收;软引用内存空间不足时会被 GC 回收;弱引用则在每次 GC 时被回收;虚引用必须和引用队列联合使用,主要用于跟踪一个对象被垃圾回收的过程。

  • Java 的异常处理机制就是 try-catch-finally 机制,需要知道异常时在 try catch 中的处理流程;需要了解 Error 和 Exception 的区别。

  • 最后 Java 的注解机制和 SPI 扩展机制可以作为扩展点适当了解。

2. 详解 Map

关于 Java 的基础知识重点讲解最常考察点 HashMap 和 ConcurrentHashMap,以及 Java 的不同版本新技术特性,如下图所示。

image.png

面试中,Map 的实现这个题目能够考察到数据结构、Java 基础实现以及对并发问题处理思路的掌握程度。

  1. HashMap
  • 先来看 HashMap 的实现,简单来说,Java 的 HashMap 就是数组加链表实现的,数组中的每一项是一个链表。通过计算存入对象的 HashCode,来计算对象在数组中要存入的位置,用链表来解决散列冲突,链表中的节点存储的是键值对。
  • 除了实现的方式,我们还需要知道填充因子的作用与 Map 扩容时的 rehash 机制,需要知道 HashMap 的容量都是 2 的幂次方,是因为可以通过按位与操作来计算余数,比求模要快。另外需要知道 HashMap 是非线程安全的,在多线程 put 的情况下,有可能在容量超过填充因子时进行 rehash,因为 HashMap 为了避免尾部遍历,在链表插入元素时使用头插法,多线程的场景下有可能会产生死循环。
  1. ConcurrentHashMap    
  • 从 HashMap 的非线程安全,面试官很自然地就会问到线程安全的 ConcurrentHashMap。ConcurrentHashMap 采用分段锁的思想来降低并发场景下的锁定发生频率,在 JDK1.7 与 1.8 中的实现差异非常大,1.7 中使用 Segment 进行分段加锁,降低并发锁定;1.8 中使用 CAS 自旋锁的乐观锁来提高性能,但是在并发度较高时性能会比较一般。另外 1.8 中的 ConcurrentHashMap 引入了红黑树来解决 Hash 冲突时链表顺序查找的问题。红黑树的启用条件与链表的长度和 Map 的总容量有关,默认是链表大于 8 且容量大于 64 时转为红黑树。这部分内容建议详细阅读源码进行学习。

3.详解 Java 版本特性

image.png

  • Java 近些年一改以往的版本发布风格,发布频率提高了很多。目前大部分公司的生产环境使用的还是 1.8 版本,一少部分升级到 1.9 或 1.10 版本,Java 的 1.8 版本是一个长期支持的版本,最新发布的 1.11 版本也是一个长期支持的版本,1.11 版本中已经包含了 1.9、1.10 版本的功能,所以 1.8 和 1.11 版本是我们要重点关注的版本。

  • 在 1.8 版本中 Java 增加了对 lambda 表达式的支持,使 Java 代码的编写可以更简洁,也更方便支持并行计算。并且提供了很多 Stream 流式处理的 API。1.8 版本还支持了方法引用的能力,可以进一步简化 lambda 表达式的写法。

  • 在 1.8 版本中,接口可以提供默认方法了,这样可以简化一些简单的抽象类。最后在 1.8 版本中对方法区进行调整,使用 Metaspace 替换掉了 PermGen 的永久代。Metaspace 与 PermGen 之间最大的区别在于:Metaspace 并不在虚拟机中,而是使用本地内存。替换的目的一方面是可以提升对元数据的管理同时提升 GC 效率,另一方面是方便后续 HotSpot 与 JRockit 合并

  • 在 1.9、1.10 版本中的主要特性是增加了模块系统,将 G1 设为默认垃圾回收器、支持局部变量推断等功能。这些功能都已经包含在 1.11 版本中。

  • 1.11 版本是 Java 最新的长期支持版本,也将会是未来一段时间的主要版本,1.11 版本中提供的最激动人心的功能是 ZGC 这个新的垃圾回收器,ZGC 为大内存堆设计,有着非常强悍的性能,能够实现 10ms 以下的 GC 暂停时间。关于 ZGC 会在下一课中进一步介绍。除此之外,1.11 版本对字符串处理 API 进行了增强,提供了字符复制等功能。1.11 版本还内置了 HttpClient。