02Java 语言特性与设计模式

本贴最后更新于 1831 天前,其中的信息可能已经时移俗易

常用的设计模式

有单例模式,工厂模式,代理模式,构造者模式,责任链模式,适配器模式,观察者模式等.

单例模式

线程安全实现的常见三种方法:

  1. 静态初始化(饿汉).不管是否使用都会创建
  2. 双重检查(懒汉).单例变量必须要用 volatile 修饰.(注意内存可见性引起的并发问题)
  3. 单例注册表.spring 中 bean 的单例模式就是用该方法实现.
// 双重检查锁的单例模式
public class Singleton {

    private volatile static Singleton uniqueSingleton;
    private Singleton() {
    }
    public Singleton getInstance() {
        if (null == uniqueSingleton) {
            synchronized (Singleton.class) {
                if (null == uniqueSingleton) {
                    uniqueSingleton = new Singleton();
                }
            }
        }
        return uniqueSingleton;
    }
}

工厂模式

这个是创建不同类型实例常用的方式。

例如 Spring 中的各种 Bean 是由不同的工厂类进行创建的

代理模式

  • 主要用在不适合或不能直接引用另一个对象的场景。
  • 可以用代理模式对被代理的队象进行访问行为的控制。
  • Java 的代理模式分为静态代理和动态代理
  • 静态代理是指在编译时就创建好的代理类。例如我们在源代码中编写的类
  • 动态代理指在 JVM 运行过程中动态创建的代理类

例如,在 Mybatis 中 getMapper 时会通过 MapperProxyFactory 及配置文件动态生成的 Mapper 代理对象,代理对象会拦截 Mapper 接口的方法调用,创建对应方法的 MapperMethod 类并执行 execute 方法,然后返回结果.
(使服务看上去就像是在使用本地的方法)

责任链模式

有点像工厂的流水线,链上的某一个节点完成对对象的某一种处理

Netty 框架在处理消息时,使用的 Pipeline 就是一种责任链模式

适配器模式

类似于转接头,把两种不适配的对象进行适配,也可以起到对两个不同的对象进行解耦的作用。

日志处理框架 SLF4J,可以跟 Log4j、logback 这种具体的日志实现框架进行解藕,通过不同适配器将 SLF4J 与 Log4j 等不同框架进行适配,完成日志功能的使用。

观察者模式

也可称为发布订阅模式,适用于一个对象的某个行为需要触发一系列事件的场景。

GRPC 中 stream 流式请求的处理就是通过观察者模式来实现的

构造者模式

适用于一个对象有很多复杂的属性,需要根据不同情况来创建不同具体的对象

创建 Protocol Buffer 对象时,需要用到 Builder 方式

Java 语言特性

动态代理与反射

  • 是 java 语言的特色,需要掌握动态代理与反射的使用场景
  • ORM 框架中会大量使用代理类
  • PRC 调用时使用反射机制调用实现类的方法

Java 常见数据类型

面试的常见问题:

  • 每种数据类型占用多大空间
    (1.byte boolean 2.char short 4.int float 8.double)
  • 数据类型的自动转换与强制转换
  • 基础数据类型与 Wrapper 数据类型的自动装箱与拆箱等

Java 对对象的引用

分为强引用、软引用、弱引用、虚引用 4 种。

这些引用在 GC 时的处理策略不同?

  • 强引用不会被 GC 回收
  • 软引用在内存空间不足时会被 GC 回收
  • 弱引用在每次 GC 时都会被 GC 回收
  • 虚引用必须和引用队列联合使用,主要用于跟踪一个对象被垃圾回收的过程

Java 的异常处理机制

就是 try/catch/finally 机制
需要知道在异常时在 try、catch 中的处理流程
需要了解 Error 和 Exception 的区别

HashMap 与 ConcurrentHashMap

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

HashMap

  • HashMap 的实现
    简单说,Java 的 HashMap 就是数组 + 链表实现的
    数组中的每一项都是一个链表
    通过计算存入对象的 HashCode,来计算对象在数组中要存入的位置,用链表来解决散列冲突,链表中的节点存储的是键值对。

  • 填充因子的作用

  • Map 扩容的 rehash 机制

  • 需要知道它的容量是二的幂次方

    是为了可以通过按位与操作来计算余数,比求模要快

  • HashMap 是非线程安全的

    在多线程 put 的情况下,有可能容量在超过填充因子时进行 rehash。因为 HashMap 为了避免尾部遍历,在链表的插入时使用的是头插法,多线程的场景下,可能会产生死循环。

ConcurrentHashMap

会从非线程安全的 HashMap 就会自然的跳转到线程安全的 ConcurrentHashMap

  • 采用分段锁的思想来降低并发场景下的锁定发生频率
  • 在 jdk1.7 和 jdk1.8 中的实现差异非常大
    • 1.7 中采用 segment 分段加锁,降低并发锁定程度
    • 1.8 中采用 CAS 自旋锁(一种乐观锁实现模式)提高性能.但在并发度较高时,性能一般.
    • 1.8ConcurrentHashMap 引入红黑树,用来解决 hash 冲突时的链表顺序查找问题。
    • 红黑树的启用条件与链表的长度和 map 的总容量有关。默认是链表大于 8,且容量大于 64 时转为红黑树方式。建立阅读源码来进行学习

Java 版本

jdk1.8 和 jdk1.11 是长期支持版本

  • jdk1.8

    • Lambda 表达式
    • StreamAPI
    • 方法引用
    • 接口默认方法
    • (对方法区进行了调整)Metaspace 替换 PermGen
      (Metaspace 与 PermGen 的最大区别在于:Metaspace 并不在虚拟机中,而是使用本地内存
      替换的目地:1.提升对源数据的处理、提升 GC 效率 2.方便后续 Hotpot 与 gearotic 合并)
  • jdk1.9-1.10

    • 模块系统
    • 默认 G1 回收器
    • 接口私有方法
    • 局部变量判断
    • Graal 编译器
  • jdk1.11

    • ZGC(最激动人心的,新的 gc 回收器)
      • 为大内存堆设计,能够实现 10ms 以下的 gc 停顿
    • 字符串 API 增强(提供了字符复制等功能)
    • 内建 HTTP Client

面试考察点

  1. 基本概念和基本原理

    要求:正确清晰

    • 网络协议 4/7 层模型的概念
    • TCP 协议流量控制的实现原理
  2. 实现方法和使用方式

    • HashMap 在 JDK1.8 中的实现方式
    • 单例模式有哪几种实现方式,什么场景该使用静态方法实现,什么场景该使用双检锁实现
  3. 经常用到的知识点

    • 常用的 Linux 命令有哪些,用来解决什么样的问题
  4. 实际应用中容易犯错的点

    • ==与 equals 区别是什么
    • 对象强引用使用不当会导致内存泄露,考察不同引用方式和作用的理解
  5. 与面试方向相关的知识点

    • 中间件:存储,网络相关的考察

加分项

  1. 知识点与典型的业务场景关联.

    如,谈到设计模型时,可以讲 XX 框架在解决 XX 问题时使用了那种设计模式.

  2. 以反例来描述实际场景中误用的危害.
    如,大量使用反射会影响性能.

  3. 与知识点相关的优化点.

    如,讲到 tcp 建连和断连时,如遇到洪水攻击或大量 TIME_WAIT 时,可以调整系统参数预防.

  4. 与知识点相关的最新技术趋势.

    如,讲到 ConcurrentHashMap,可以介绍 1.8 的改进细节.

    或,讲到 HTTP 时,能说出 HTTP2 和 QUIC 的特点和实现.

  5. 在了解的前提下,尽量增加回答内容深度.

    如,讲到 tcp 的滑动窗口时,能讲到流量与拥塞控制,进一步能指出解决拥塞的不同算法.

真题汇总-1

  1. 进程和线程的区别和联系

    从资源占用,切换效率,通信方式等方面解答

  2. 简单介绍一下进程的切换过程

    线程上下文的切换代价,要回答,切换会保存寄存器,栈等线程相关的现场,需要由用户态切换到内核态,可以用 vmstat 命令查看线程上下文的切换状况

  3. 你经常使用哪些 Linux 命令,主要用来解决哪些问题?

    参考之前操作系统汇总中提到的命令

  4. 为什么 TCP 建连需要 3 次握手而断连需要 4 次?
    参考之前内容

  5. 为什么 TCP 关闭链接时需要 TIME_WAIT 状态,为什么要等 2MSL?

    参考之前内容

  6. 一次完整的 HTTP 请求过程是怎样的?

    DNS 解析,TCP 建连,HTTP 请求,HTTP 响应等.
    实际回答时可以画一个简单的交互图

  7. HTTP2 和 HTTP 的区别有哪些?

  8. 在你的项目中你使用过哪些设计模式?主要用来解决哪些问题?

  9. Object 中的 equals 和 hashcode 的作用分别是什么?

  10. final,finally,finalize 的区别与使用场景

  11. 简单表述一下 Java 的异常机制

  12. 线上上使用的那个版本 jdk,为什么使用这个版本(有什么特色)?

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    198 引用 • 120 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...