前言
Android 开发岗位竞争激烈,想要在大厂面试中脱颖而出,必须全面梳理知识点,扩充题库,并针对关键知识进行深入分析。本文汇总了多年大厂面经总结及核心考点深度解析,涵盖 JVM、并发编程、设计模式及 Android 核心机制等内容。
Android 面试真题
JVM 的加载原理
1. 编译机制
Java 文件经过一次编译后,生成 Java 字节码(class 文件)。然后在不同平台上使用不同的虚拟机(JVM)解释执行成机器码。这体现了 Java'一次编译,到处运行'的特性。在 Mac 系统上运行只需安装对应的 JVM 即可。
2. 类的加载机制
类加载过程主要分为以下阶段:
1. 加载 分为三步:获取二进制字节流;将静态存储结构转换为方法区中的运行时数据结构;生成一个对象放入 Java 堆中,作为对方法区的引用。
2. 验证 确保 class 文件的表示(魔数)、版本号、字段表、方法表、常量池、元数据及字节码指令的正确性。若任何一项验证失败,则加载终止。
3. 准备 为类变量分配内存并设置默认初始化值。此阶段仅处理 static 类变量。如果是 final 类型且为常量,会直接赋值到常量池中。
4. 解析 将符号引用替换为直接引用(指针或偏移量),涉及类、接口、字段和方法的解析。
5. 初始化
执行 <clinit> 方法,对静态变量和静态代码块进行初始化。
6. 使用 正常使用该 Class 对象。
7. 卸载 当 Class 不再被使用时,由 GC 卸载。
3. 类加载器
类加载遵循双亲委派模型。自定义加载器的父类是 AppClassLoader,其父类是 ExtClassLoader,最顶层是 BootstrapClassLoader。
加载类时,从当前类加载器开始,逐级向上委托给父加载器查找。这种机制保证了类的安全性和唯一性,即一个类只会被加载一次。判断两个对象是否相同的重要条件之一是它们是否由同一个类加载器加载。
全局变量和局部变量的区别
- 定义位置与作用域:全局变量在函数外部定义,作用域是整个源程序文件;局部变量在函数内部定义,作用域仅限于函数内。
- 生命周期:全局变量在程序运行期间一直存在;局部变量仅在函数执行期间存在,函数结束即销毁。
- 同名处理:同一源文件中允许全局变量和局部变量同名,局部变量优先。
- 存储方式:全局变量、静态局部变量、静态全局变量均在静态存储区分配空间;普通局部变量在栈里分配空间。
- static 修饰的影响:
- 静态局部变量:具有局部作用域,但生命周期贯穿整个程序运行期。
- 静态全局变量:具有文件作用域,仅在定义它的源文件内有效,避免与其他文件同名变量冲突。
Tips:
- 若全局变量仅在单个 C 文件中访问,建议改为静态全局变量以降低耦合度。
- 若全局变量仅由单个函数访问,可改为该函数的静态局部变量。
- 涉及重入问题时,需避免使用 static 变量。
- 函数返回指针时,若需返回局部变量地址,必须使用 static 修饰。
静态方法锁和非静态方法锁区别
- 锁对象不同:静态方法锁的是类对象(Class 对象),非静态方法锁的是实例对象。
- 互斥范围:
- 类对象被 lock,该类所有同步静态方法(
static synchronized)全被 lock。 - 实例对象被 lock,该实例对象的所有同步方法(
synchronized)全被 lock。
- 类对象被 lock,该类所有同步静态方法(
- :如果调用方法的对象相同,锁必然相同;否则不同。例如 和 ,对象不同,锁不同。若 A 是单例,则能互斥。


