aoi学院

Aisaka's Blog, School of Aoi, Aisaka University

Java-面试基础内容

JAVA

⭐ java八种基本数据类型

byte、short、int、long、float、double、char、boolean

⭐ string、stringBuilder、stringBuffer

final byte[], byte[], synchronized

⭐ 四种引用的区别和作用

强引用:最常见、即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。

软引用:如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收;只有在内存空间不足时,软引用才会被垃圾回收器回收。

弱引用:拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象。

虚引用:如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

⭐⭐ hashmap的数据结构

数组+链表(6)/红黑树(8),头插,hashcode模运算位运算,默认1<<4桶负载因子0.75扩容<<1

⭐⭐ 什么是可达性分析

GC,引用计数法和可达性分析,Root节点:栈引用、static、final、native

⭐⭐ 类加载机制

  • 类加载的时机

    • 隐式加载 new 创建类的实例
    • 显式加载:loaderClass,forName等
    • 访问类的静态变量,或者为静态变量赋值
    • 调用类的静态方法
    • 使用反射方式创建某个类或者接口对象的Class对象。
    • 初始化某个类的子类
    • 直接使用java.exe命令来运行某个主类
  • 类加载的过程

    • 加载:ClassLoader通过一个类的完全限定名查找此类字节码文件,并利用字节码文件创建一个class对象。
    • 验证:确保class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身的安全,主要包括四种验证:文件格式的验证,元数据的验证,字节码验证,符号引用验证。
    • 准备:类变量(static修饰的字段变量)分配内存并且设置该类变量的初始值,(如static int i = 5 这里只是将 i 赋值为0,在初始化的阶段再把 i 赋值为5),这里不包含final修饰的static ,因为final在编译的时候就已经分配了。这里不会为实例变量分配初始化,类变量会分配在方法区中,实例变量会随着对象分配到Java堆中。
    • 解析:把常量池中的符号引用替换成直接引用
    • 初始化:如果该类具有父类就进行对父类进行初始化,执行其静态初始化器(静态代码块)和静态初始化成员变量。(前面已经对static 初始化了默认值,这里我们对它进行赋值,成员变量也将被初始化)
  • 双亲委派机制

    • 如果一个类收到了类加载的请求,它并不会自己先去加载,而是把这个请求委托给父类加载器去执行,如果父类加载器还存在父类加载器,则进一步向上委托,依次递归,请求最后到达顶层的启动类加载器,如果能够完成类的加载任务,就会成功返回,倘若父类加载器无法完成任务,子类加载器才会尝试自己去加载。

⭐⭐ 线程同步

java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突。

  1. synchronized:java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。也可以修饰语句块会,从而实现同步。

  2. volatile:使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,同时防止指令重排

  3. 重入锁:ReentrantLock类是可重入、互斥、实现了Lock接口的锁,它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力。

  4. 局部变量:使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。

  5. 阻塞队列:前面5种同步方式都是在底层实现的线程同步,但是我们在实际开发当中,应当尽量远离底层结构。使用java.util.concurrent包LinkedBlockingQueue来实现线程的同步,队列是先进先出的顺序(FIFO)。

  6. 原子变量:java.util.concurrent.atomic包提供了创建了原子类型变量的工具类。其中AtomicInteger可以用原子方式更新int的值,可用在应用程序中(如以原子方式增加的计数器),但不能用于替换Integer;可扩展Number,允许那些处理基于数字类的工具和实用工具进行统一访问。

⭐⭐ 线程中断

  1. interrupt():仅设置中断标识位

  2. isInterrupted():只测试线程是否已经中断,中断标识位的状态并不受到该方法的影响

  3. static interrupted():测试当前线程是否已经中断,线程的中断标识位由该方法清除。interrupted()方法和isInterrupted()方法调用的是同一个native方法,无非这个方法传入的是true,表示清除中断标识位

⭐⭐⭐ 设计一个可重入锁

主要关键是lock()和unlock()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MyLock implements Lock {

private boolean isLocked = false;

@Override
public synchronized void lock() {
while(isLocked) {
try {
wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
isLocked = true;
}
// ......
@Override
public synchronized void unlock() {
isLocked = false;
notifyAll();
}
}

计算机网络

⭐ TCP/IP模型几层

⭐⭐ 端口号位于哪一层?如果TCP和UDP访问同一个端口号会怎么样?

传输层(TCP、UDP),可以,在ip报文里有个叫做协议的字段,指出了上层协议是TCP还是UDP还是其他P。

⭐⭐ TCP如何保证其可靠

校验和,确认应答+序列号,超时重传,三次握手四次挥手,流量控制(滑动窗口),拥塞控制(慢开始、拥塞避免、快重传、快恢复)

⭐⭐ HTTP哪些操作是幂等的

http幂等操作:get/put/delete

http非幂等操作:post/patch


操作系统

⭐ 什么是缺页中断

缺页中断就是要访问的页不在主存,需要操作系统将其调入主存后再进行访问。

页面置换算法:先进先出置换算法(FIFO)、最近最久未使用算法(LRU)、最少使用置换算法(LFU)、最佳置换算法(OPT)……

⭐ 什么是虚拟内存

虚拟内存是一种计算机系统内存管理技术。它使得应用程序认为它拥有连续可用的内存,即一个连续完整的地址空间。而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。

电脑中所有运行的程序都需要经过内存来执行,如果执行的程序很大或很多,就会导致内存消耗殆尽。为了解决这个问题,WINDOWS运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,这部分空间即称为虚拟内存。

⭐ 为什么要区分用户态和内核态

CPU将指令分为特权指令和非特权指令,对于那些危险的指令,只允许操作系统及其相关模块使用,如果错用,将导致整个系统崩溃。比如:清内存、设置时钟等。


数据库

⭐ 什么是索引及索引的作用

索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构。

快速取数据;保证数据记录的唯一性;实现表与表之间的参照完整性;在使用order by、group by子句进行数据检索时,利用索引可以减少排序和分组的时间

⭐ 数据库事务ACID

  1. 原子性(Atomicity):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

  2. 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

  3. 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

  4. 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

⭐ 数据库隔离级别

事务的隔离级别脏读不可重复读幻读
读未提交(Read uncommitted)
读提交(Read committed–Sql Server , Oracle)×
重复读(Repeatable read–MySQL)××
序列化(Serializable)×××

Android

⭐ 怎么查看是否内存泄漏

Android Profiler、LeakCanary

⭐ Activity启动模式

Standard、SingleTop、SingleTask、SingleInstance

https://www.bilibili.com/video/BV1CA41177Se

⭐⭐ 内存泄漏的原因及如何避免

以下情况需关注是否会内存泄漏:Static Activities、Static Views、Inner Classes、Anonymous Classes、Handler、Threads、TimerTask、Sensor Manager

一般内存泄漏:忘记释放分配的内存,例如cursor

逻辑内存泄漏:当应用不再需要这个对象或结束生命周期,仍未释放该对象的所有引用

在Android中,导致潜在内存泄漏的陷阱:

  1. 全局进程的static变量,这个无视应用的状态,持有Activity的强引用

  2. 活在Activity生命周期外的线程,没有清空对Activity的强引用