Android 开发核心面试题与答案详解
前言
本文整理了 Android 开发中常见的 Java 基础、Android 组件通信、Framework 原理及 Flutter 架构面试题。涵盖抽象类与接口区别、线程状态管理、Handler 机制、Binder 跨进程通信、Activity 生命周期及 Flutter 渲染树等核心知识点,并提供详细解答与技术解析,帮助开发者系统复习面试重点。
Java 篇
一、抽象类与接口的区别?
在 Java 面向对象编程中,抽象类(Abstract Class)和接口(Interface)都是实现代码复用和约束的手段,但设计意图不同。
- 方法实现:抽象类可以提供成员方法的实现细节,也可以包含抽象方法;而接口在 Java 8 之前只能存在 public 抽象方法,Java 8 之后支持 default 方法和 static 方法,但仍以定义行为契约为主。
- 成员变量:抽象类中的成员变量可以是各种类型(public, private, protected 等),可以有实例变量;接口中的成员变量只能是 public static final 类型的常量。
- 构造器与静态块:接口中不能含有构造器、静态代码块以及普通静态方法(Java 8+ 除外),而抽象类可以有构造器、静态代码块和静态方法,用于初始化状态。
- 继承关系:一个类只能继承一个抽象类(单继承),而一个类却可以实现多个接口(多实现)。这体现了 Java 的多态性限制。
- 性能差异:抽象类访问速度通常比接口快,因为接口需要时间去寻找在类中具体实现的方法(涉及动态查找),而抽象类是静态绑定。但在现代 JVM 优化下,这种差异已不明显。
- 扩展性:如果你往抽象类中添加新的非抽象方法,你可以给它提供默认的实现,因此不需要改变现有的子类代码。如果你往接口中添加方法,那么所有实现该接口的类都必须实现该方法,否则编译报错。
- 设计目的:接口更多的为了约束类的行为,可用于解耦,强调'能做什么';抽象类更加侧重于代码复用,强调'是什么',适合有共同状态的类。
二、谈谈 List, Set, Map 的区别?
这三个是 Java 集合框架的核心接口,存储逻辑和数据结构不同。
- List:有序集合,允许重复元素。底层实现包括 ArrayList(基于数组,查询快插入慢)、LinkedList(基于双向链表,插入删除快查询慢)。索引访问效率高。
- Set:无序集合(HashSet),不允许重复元素。元素在集合中的位置是由元素的 hashcode 决定。Set 集合是根据 hashcode 来进行数据存储的,所以位置是固定的,但是这个位置不是用户可以控制的,所以对于用户来说 set 中的元素还是无序的。TreeSet 则根据自然顺序或比较器排序。
- Map:键值对映射,键(Key)不允许重复,值(Value)允许重复。存储的数据是无序的(HashMap),或者按 Key 排序(TreeMap)。常用实现有 HashMap(哈希表)、LinkedHashMap(维护插入顺序)、ConcurrentHashMap(线程安全)。
三、说一下线程的几种状态?
Java 线程生命周期由 java.lang.Thread.State 枚举定义,主要包括以下五种状态:
- 新建状态(NEW):在生成线程对象,并没有调用该对象的 start 方法,这是线程处于创建状态。此时线程还未开始运行。
- 就绪状态(RUNNABLE):当调用了线程对象的 start 方法之后,该线程就进入了就绪状态。此时线程调度程序还没有把该线程设置为当前线程,它正在等待 CPU 时间片。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
- 运行状态(RUNNING):线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行 run 函数当中的代码。注意 RUNNABLE 状态在 Java 中既包含就绪也包含运行。
- 阻塞状态(BLOCKED):线程正在运行的时候,被暂停,通常是为了等待某个时间的发生 (比如说某项资源就绪) 之后再继续运行。sleep(), suspend(), wait() 等方法都可以导致线程阻塞。其中 synchronized 锁竞争失败会进入 BLOCKED 状态。
- 死亡状态(TERMINATED):如果一个线程的 run 方法执行结束或者调用 stop 方法后,该线程就会死亡。对于已经死亡的线程,无法再使用 start 方法令其进入就绪。


