Java面试八股文知识点随笔

复习关键字

  • new对象的过程
  • 类加载过程
    • 双亲委派机制
    • 类加载器
  • Synchronized,Reentrantlock和AQS
  • Java新版本特性
  • 集合源码
    • 红黑树
  • 两种代理模式
  • IO模型,三种javaIO模型
  • 数据库主从分离方式
    • 代理方式
    • 组件方式

框架了解

算法

  • KMP算法
  • variable-precision SWAR算法
  • RAFT算法

使用 try-with-resources 代替try-catch-finally

适用于java7之后的特性,针对字节流和网络连接之类的对象,不再需要每次在finally中进行close

try-catch-finally风格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//读取文本文件的内容
Scanner scanner = null;
try {
scanner = new Scanner(new File("D://read.txt"));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}

try-with-resources风格

1
2
3
4
5
6
7
8
9
10
try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new File("test.txt")));
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) {
int b;
while ((b = bin.read()) != -1) {
bout.write(b);
}
}
catch (IOException e) {
e.printStackTrace();
}

在 Java 9 之后,在 try-with-resources 语句中可以使用 effectively-final 变量。

1
2
3
4
5
6
// effectively-final简单说就是被初始化后从未变更的变量,如下用final修饰符的scanner和未被final修饰的writer,都未曾改变,因此就是effectively-final变量
final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) {
// omitted
}

静态方法为什么不能调用非静态成员?

简单来说静态方法初始化在类加载时,非静态成员初始化于new 实例对象时

深拷贝和浅拷贝区别了解吗?什么是引用拷贝?

为什么重写 equals() 时必须重写 hashCode() 方法?

hashcode相等时,两对象不一定相等。但如果两对象相等,那hashcode必定相等。即hashcode是两对象相等的必要不充分条件。

为什么 Java 中只有值传递

还可以参见Java 到底是值传递还是引用传递? - Hollis的回答 - 知乎

Java 序列化详解

序列化一般用于数据-文件转换和网络传输
序列化方式
JDK自带 性能较差,一般不用
kyro 高性能
Protobuf 高性能,跨语言,略烦琐,google在用
ProtoStuff Protobuf升级版,更简洁易用
hessian 较老,跨语言,dubbo在使用hessian2

BigDecimal 详解

集合总结

  • List(对付顺序的好帮手): 存储的元素是有序的、可重复的。
  • Set(注重独一无二的性质): 存储的元素是无序的、不可重复的。
  • Queue(实现排队功能的叫号机): 按特定的排队规则来确定先后顺序,存储的元素是有序的、可重复的。
  • Map(用 key 来搜索的专家): 使用键值对(key-value)存储,类似于数学上的函数 y=f(x),”x” 代表 key,”y” 代表 value,key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值。
  • 虽然理论上linkedList的头尾插入和删除比ArrayList更快,但是实际一般都会在中间位置插入,这个时候差别并不大,而ArrayList的其他性能几乎都更好,因此实践中几乎不会用到LinkedList
  • ArrayList 实现了 RandomAccess 接口,而 LinkedList 没有实现。RandomAccess更多是一个标示,其接口内容是空的,本质上是因为ArrayList底层实现是数组,因此支持随机访问,而不是实现了RandomAccess才支持随机访问。

HashMap 的长度为什么是 2 的幂次方

hash值通过对数组的长度进行取模运算得到在数组中的位置
取余(%)操作中如果除数是 2 的幂次则等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是 length 是 2 的 n 次方;)

ArrayList中ensurecapacity方法

最好在 add 大量元素之前用 ensureCapacity 方法,以减少增量重新分配的次数

说说线程的生命周期和状态

线程有六种状态:NEW,RUNNABLE,BLOCKED,WAITING,TIME_WAITING,TERMINATED
其中RUNNABLE状态包含READY和RUNNING两种状态,由于切换时间很短,因此并未做区分

为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法

调用 start() 方法方可启动线程并使线程进入就绪状态,直接执行 run() 方法的话不会以多线程的方式执行。

AQS介绍

AQS 的全称为(AbstractQueuedSynchronizer),是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出大量应用广泛的同步器,比如我们提到的 ReentrantLock,Semaphore,其他的诸如 ReentrantReadWriteLock,SynchronousQueue,FutureTask 等等皆是基于 AQS 的。