当前位置: 首页 > java >正文

百度移动开发面经合集

1、对线程安全的理解

线程安全是指在多线程环境下,某个函数、类或数据结构能够正确地处理多个线程的并发访问,而不会出现数据竞争、不一致或其他不可预期的行为。线程安全的实现通常需要考虑以下几点:

  • 原子性:操作是不可分割的,要么全部执行,要么全部不执行。

  • 可见性:一个线程对共享数据的修改能够及时被其他线程看到。

  • 有序性:程序的执行顺序符合预期,避免指令重排导致的问题。

实现线程安全的方法包括:

  • 使用同步机制(如锁、信号量)。

  • 使用线程安全的数据结构(如 ConcurrentHashMap)。

  • 避免共享状态(如使用局部变量或线程本地存储)。

2、对链表的使用和理解,链表有哪几种并举例应用场景

链表是一种线性数据结构,由节点组成,每个节点包含数据和指向下一个节点的指针。链表的类型包括:

  1. 单向链表:每个节点只有一个指针指向下一个节点。

    • 应用场景:实现栈、队列、简单的动态集合。

  2. 双向链表:每个节点有两个指针,分别指向前一个和后一个节点。

    • 应用场景:需要双向遍历的场景(如浏览器的前进后退、LRU缓存)。

  3. 循环链表:尾节点指向头节点,形成环。

    • 应用场景:轮询调度、环形缓冲区。

链表的优点是插入和删除高效(O(1)),缺点是随机访问慢(O(n))。

3、TCP 相对于 UDP 有哪些优点,两者的不同点

TCP的优点

  • 可靠传输:通过确认、重传、流量控制和拥塞控制确保数据不丢失、不重复、按序到达。

  • 面向连接:通信前需要建立连接(三次握手),通信后释放连接(四次挥手)。

  • 适合对可靠性要求高的场景(如文件传输、网页浏览)。

TCP vs UDP

特性TCPUDP
可靠性可靠不可靠
连接面向连接无连接
传输效率较低(开销大)较高(开销小)
数据顺序保证顺序不保证顺序
应用场景HTTP、FTP、SSH视频流、DNS、游戏

4、讲述一下TCP 的传送数据的过程

  1. 建立连接(三次握手):

    • 客户端发送 SYN=1, seq=x

    • 服务端回复 SYN=1, ACK=1, seq=y, ack=x+1

    • 客户端发送 ACK=1, seq=x+1, ack=y+1

  2. 数据传输

    • 发送方将数据分割为报文段,按序发送。

    • 接收方确认收到数据(ACK)。

    • 发送方未收到ACK时会重传。

  3. 释放连接(四次挥手):

    • 客户端发送 FIN=1, seq=u

    • 服务端回复 ACK=1, ack=u+1

    • 服务端发送 FIN=1, seq=v

    • 客户端回复 ACK=1, ack=v+1

5、原子性和一致性

  • 原子性(Atomicity):事务中的操作要么全部成功,要么全部失败(如转账:A减钱和B加钱必须同时完成)。

  • 一致性(Consistency):事务执行前后,数据库从一个一致状态变到另一个一致状态(如满足约束条件)。

6、数据库的索引和事务是什么

  • 索引:加速查询的数据结构(如B+树索引)。优点:提高查询速度;缺点:占用空间,降低插入/更新速度。

  • 事务:一组操作的逻辑单元,满足ACID特性(原子性、一致性、隔离性、持久性)。

7、数据库查询操作有哪些可以提高查询效率的优化

  1. 使用索引。

  2. 避免 SELECT *,只查询需要的列。

  3. 优化JOIN操作(小表驱动大表)。

  4. 避免全表扫描(如避免对索引列使用函数)。

  5. 分库分表(大数据量时)。

  6. 使用缓存(如Redis)。

8、手写快排的代码

public class QuickSort {public static void quickSort(int[] arr, int low, int high) {if (low < high) {int pivotIndex = partition(arr, low, high);quickSort(arr, low, pivotIndex - 1);  // 递归排序左子数组quickSort(arr, pivotIndex + 1, high); // 递归排序右子数组}}private static int partition(int[] arr, int low, int high) {int pivot = arr[high];  // 选择最右元素作为基准int i = low - 1;         // i是小于基准的元素的边界for (int j = low; j < high; j++) {if (arr[j] < pivot) {i++;swap(arr, i, j);  // 将小于基准的元素放到左侧}}swap(arr, i + 1, high);  // 将基准放到正确位置return i + 1;}private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void main(String[] args) {int[] arr = {3, 6, 8, 10, 1, 2, 1};quickSort(arr, 0, arr.length - 1);System.out.println(Arrays.toString(arr)); // 输出: [1, 1, 2, 3, 6, 8, 10]}
}

9、展示曾经写过的项目代码并讲述功能

为什么选择做安卓

我选择做安卓开发的原因主要有以下几点:

  • 用户基数大:Android 是全球市场份额最大的移动操作系统,拥有庞大的用户群体。

  • 开放性和灵活性:相比 iOS,Android 系统更开放,允许开发者更自由地定制和优化应用。

  • 技术生态丰富:Android 开发涉及 UI/UX、性能优化、多线程、网络通信等多个领域,技术挑战性强。

  • 跨平台趋势:Kotlin、Flutter、Jetpack Compose 等技术的发展让 Android 开发更具扩展性。

此外,我对移动端交互和性能优化有浓厚兴趣,Android 开发能让我深入理解系统底层机制(如 Binder、Handler 等),提升综合技术能力。

安卓了解多少,技术非技术都可以

技术方面

  • 开发语言:Java(传统)、Kotlin(官方推荐,更简洁安全)。

  • 核心组件:Activity(界面)、Service(后台)、BroadcastReceiver(广播)、ContentProvider(数据共享)。

  • UI 框架:XML + View 体系、Jetpack Compose(声明式 UI)。

  • 架构模式:MVC → MVP → MVVM(DataBinding + ViewModel + LiveData)。

  • 性能优化:内存泄漏(LeakCanary)、卡顿分析(Systrace)、APK 瘦身(ProGuard)。

  • 新技术:协程(Kotlin Flow)、KMM(跨平台)、Android 12/13 新特性(如 Material You)。

非技术方面

  • 市场现状:Android 占据全球约 70% 移动市场份额,但国内厂商深度定制(如 MIUI、EMUI)。

  • 开发者生态:Google Play 审核较宽松,但国内需适配各大应用商店。

  • 挑战:碎片化严重(系统版本、屏幕尺寸、厂商 ROM 差异)。

聊项目,登录采用的redis+cookie的分布式session解决方案,具体聊聊

在分布式系统中,Session 需共享,避免用户登录状态丢失(如服务器重启或负载均衡切换)。

实现方案

  1. 登录流程

    • 用户输入账号密码,服务端校验通过后生成唯一 SessionID

    • 将 SessionID:UserInfo 存入 Redis(设置过期时间)。

    • 通过 Set-Cookie 将 SessionID 返回给浏览器。

  2. 后续请求

    • 浏览器自动携带 Cookie(SessionID)

    • 服务端从 Redis 查询 SessionID,获取用户信息。

  3. 安全性优化

    • Cookie 设置 HttpOnly 防 XSS,Secure 强制 HTTPS。

    • Redis 存储的 Session 可加密(如 JWT)。

优点

  • 无状态:服务端无需存储 Session,适合横向扩展。

  • 高可用:Redis 集群保障 Session 不丢失。

登录过程当中对密码的校验,存储讲讲

校验流程

  1. 前端对密码做初步校验(如长度、复杂度)。

  2. 服务端二次校验(防恶意请求),例如:

    if (password.length() < 8 || !containsLetterAndDigit(password)) {throw new InvalidPasswordException();
    }

     

存储方案

  • 哈希加密:使用 BCrypt(推荐)或 PBKDF2,避免明文存储。

    String hashedPassword = BCrypt.hashpw(rawPassword, BCrypt.gensalt());

     

  • 加盐(Salt):防止彩虹表攻击,每个用户密码使用独立随机盐值。

面向对象的三大特性具体讲解下

封装(Encapsulation)

  • 隐藏内部实现,暴露安全接口。

继承(Inheritance)

  • 子类复用父类属性和方法(extends)。

多态(Polymorphism)

  • 同一方法在不同子类中有不同实现(覆盖 @Override + 父类引用指向子类对象)。

讲讲java的权限控制(protect继承关系,default是包访问权限)

修饰符类内同包子类其他包
private
default
protected
public
  • protected:子类可访问(即使跨包)。

  • default(包权限):仅同包内可见。

java基本类型的以及占空间大小

类型大小取值范围
boolean1字节true/false
byte1字节-128 ~ 127
short2字节-32768 ~ 32767
int4字节-2³¹ ~ 2³¹-1
long8字节-2⁶³ ~ 2⁶³-1
float4字节IEEE 754 单精度浮点
double8字节IEEE 754 双精度浮点
char2字节Unicode 字符(0~65535)

注意:JVM 可能对 boolean 优化为 1 bit,但数组中占 1 字节。

boolean类型占多大内存,int占多少,double(8字节)

如上

java循环的使用

(1) for 循环

(2) while 循环

(3) do-while 循环

(4) 增强 for(遍历集合)

java的反射机制,单例模式被反射机制破环,具体是反射的哪些Api进行破环的

Java 反射可以过 Class.getDeclaredConstructor() 和 Constructor.setAccessible(true) 绕过单例模式的私有构造方法限制,从而创建多个实例。

防御反射攻击的方法

  • 枚举单例(推荐):JVM 保证枚举实例的唯一性,反射无法破坏。

  • 构造方法中抛出异常

简单介绍单例模式的实现方式都有哪些

实现方式特点线程安全防反射
饿汉式类加载时初始化,可能浪费资源
懒汉式第一次调用时初始化,需加锁解决线程问题❌(需同步)
双重检测锁延迟加载 + 同步块优化性能
静态内部类利用类加载机制保证线程安全,延迟加载
枚举最安全,JVM 保障唯一性,天然防反射和序列化破坏

双重检测锁的模式可以解决懒汉式单例的存在的多线程问题,请问枚举可以解决单例模式存在的

单例模式的优势

  1. 线程安全:JVM 在加载枚举类时保证实例唯一。

  2. 防反射攻击Constructor.newInstance() 会直接抛出异常。

  3. 防序列化破坏:枚举的序列化由 JVM 特殊处理,不会创建新实例。

java当中的集合八股

集合框架分类

  • Collection

    • List:有序可重复(ArrayListLinkedList)。

    • Set:无序不重复(HashSetTreeSet)。

    • Queue:队列(LinkedListPriorityQueue)。

  • Map

    • HashMap:数组 + 链表/红黑树。

    • TreeMap:基于红黑树有序。

    • ConcurrentHashMap:线程安全。

高频考点

  • ArrayList vs LinkedList

  • HashMap 的哈希冲突解决(拉链法 + 红黑树)。

  • ConcurrentHashMap 的分段锁(JDK7)和 CAS + synchronized(JDK8)。

HashMap的扩容机制

  1. 触发条件:当元素数量超过 容量 × 负载因子(默认 0.75) 时扩容。

  2. 扩容过程

    • 新建一个 2 倍大小的数组。

    • 重新计算每个键值对的哈希值,分配到新数组(JDK8 优化:高位掩码判断位置是否变化)。

  3. JDK8 优化:链表长度 ≥8 时转红黑树(提高查询效率)。

Java多线程当中的锁

锁的分类

  1. synchronized

    • 修饰方法或代码块,JVM 级别实现。

    • 可重入,非公平锁。

  2. ReentrantLock

    • API 级别锁,需手动 lock()/unlock()

    • 支持公平锁、可中断、条件变量(Condition)。

  3. ReadWriteLock

    • 读写分离(ReentrantReadWriteLock),提高读多写少场景性能。

  4. StampedLock

    • 乐观读锁,避免写线程饥饿。

在项目当中使用过哪些锁,怎么使用的

new对象的时候,JVM底层的一个过程(类加载机制)

当执行 new MyClass() 时,JVM 底层会经历以下步骤:

(1) 类加载(若未加载)

  • 加载(Loading)

    • 通过类加载器(ClassLoader)查找 .class 文件,将字节码加载到方法区。

    • 生成 Class 对象(存储在堆中,作为方法区数据的访问入口)。

  • 验证(Verification):检查字节码合法性(如魔数、语法)。

  • 准备(Preparation):为静态变量分配内存并赋默认值(如 int 初始化为 0)。

  • 解析(Resolution):将符号引用(如类名、方法名)转为直接引用(内存地址)。

  • 初始化(Initialization):执行静态代码块(static{})和静态变量赋值。

(2) 对象实例化

  • 分配内存

    • 指针碰撞(堆内存规整时):移动指针分配连续空间。

    • 空闲列表(堆内存不规整时):从空闲内存块列表中选择合适区域。

  • 内存空间初始化:将所有字段置为默认值(如 int 为 0,引用为 null)。

  • 设置对象头:存储 Mark Word(哈希码、GC 分代年龄等)和类元数据指针(指向方法区的 Class 对象)。

  • 执行构造方法<init>):调用用户定义的构造函数,完成字段赋值。

(3) 对象引用关联

  • 将堆中对象的内存地址赋给栈中的引用变量(如 MyClass obj)。

讲讲网络当中Https

HTTPS = HTTP + SSL/TLS,核心是通过加密和证书保障安全:

(1) 加密流程(TLS 握手)

  1. 客户端发起请求

    • 发送支持的加密算法列表和随机数(Client Random)。

  2. 服务器响应

    • 返回选择的加密算法、服务器证书(含公钥)和随机数(Server Random)。

  3. 证书验证

    • 客户端用 CA 机构的公钥验证证书合法性(防中间人攻击)。

  4. 生成会话密钥

    • 客户端用服务器公钥加密一个 Pre-Master Secret 并发送。

    • 双方通过 Client Random + Server Random + Pre-Master 生成对称密钥(Session Key)。

  5. 加密通信

    • 后续数据传输使用 Session Key 对称加密(如 AES)。

(2) 关键点

  • 非对称加密:用于密钥交换(RSA/ECDHE)。

  • 对称加密:用于数据传输(AES)。

  • 数字证书:验证服务器身份,由 CA 机构签发。

刚刚提到的Https是基于Http,Http使用的是Tcp,那么Tcp的四次挥手当中第三次挥手是谁向谁进行挥手

在 TCP 四次挥手中:

  1. 第一次挥手:客户端 → 服务器,发送 FIN=1(客户端主动关闭)。

  2. 第二次挥手:服务器 → 客户端,发送 ACK=1(确认收到 FIN)。

  3. 第三次挥手:服务器 → 客户端,发送 FIN=1(服务器准备关闭)。

  4. 第四次挥手:客户端 → 服务器,发送 ACK=1(确认收到 FIN)。

关键问题答案

  • 第三次挥手是服务器向客户端发送 FIN,表示服务器数据已发送完毕,准备关闭连接。

为什么需要四次挥手?

  • TCP 是全双工的,双方需独立关闭自己的发送通道。

  • 第二次和第三次挥手不能合并:服务器可能还有数据要发送(延迟确认)。

总结:

  1. new 对象过程:类加载 → 分配内存 → 初始化 → 构造方法调用。

  2. HTTPS:通过 TLS 握手建立安全通道,混合使用非对称加密和对称加密。

  3. TCP 挥手:第三次挥手是服务器通知客户端关闭连接。

数据结构当中栈和队列在项目使用过嘛

算法题:两个栈实现一个队列

队列(Queue)是 先进先出(FIFO) 的数据结构,而栈(Stack)是 后进先出(LIFO) 的数据结构。我们可以利用 两个栈(stack1 和 stack2 来模拟队列的操作:

核心思想

  1. 入队(enqueue:直接压入 stack1

  2. 出队(dequeue

    • 如果 stack2 为空,则把 stack1 的所有元素弹出并压入 stack2(此时 stack2 的栈顶就是最早入队的元素)。

    • 如果 stack2 不为空,直接弹出栈顶元素。

.工作内容简单介绍(10min)

2.介绍一下TCP三握四次挥手(10min)

三次握手(建立连接)

  1. SYN(Client → Server):

    • 客户端发送 SYN=1, seq=x(随机序列号)。

  2. SYN+ACK(Server → Client):

    • 服务端返回 SYN=1, ACK=1, seq=y, ack=x+1(确认客户端的 x,并发送自己的 y)。

  3. ACK(Client → Server):

    • 客户端发送 ACK=1, seq=x+1, ack=y+1(确认服务端的 y)。

✅ 目的:确保双方都有发送和接收能力,防止历史连接干扰。

四次挥手(关闭连接)

  1. FIN(Client → Server):

    • 客户端发送 FIN=1, seq=u(表示不再发送数据)。

  2. ACK(Server → Client):

    • 服务端返回 ACK=1, ack=u+1(确认收到 FIN)。

  3. FIN(Server → Client):

    • 服务端发送 FIN=1, seq=v(表示服务端也准备关闭)。

  4. ACK(Client → Server):

    • 客户端返回 ACK=1, ack=v+1(确认服务端的 FIN)。

✅ 为什么需要四次?

  • TCP 是全双工的,双方需独立关闭自己的发送通道。

2.1为什么第四次挥手要超时等待2MSL

MSL(Maximum Segment Lifetime):报文最大生存时间(Linux 默认 60s)。

  • 目的 1:确保最后一个 ACK 能到达服务端。

    • 如果服务端没收到 ACK,会重发 FIN,客户端在 2MSL 内还能响应。

  • 目的 2:让本次连接的所有报文在网络中消失,避免影响后续新连接。

2.2如果有大量的time_wait,close_wait,你会如何检测分析,原因?出现阶段?以及如何避免

(1)TIME_WAIT(客户端状态)

  • 出现阶段:主动关闭连接的一方(如 HTTP 客户端、微服务调用方)。

  • 原因

    • 短连接频繁建立和关闭(如爬虫、API 频繁调用)。

    • 没有复用 TCP 连接(如 HTTP/1.1 未启用 Keep-Alive)。

  • 解决

  • 复用连接(HTTP/1.1 Keep-Alive、连接池)。

  • 调整内核参数(慎用):

(2)CLOSE_WAIT(服务端状态)

  • 出现阶段:被动关闭连接的一方(如服务端未正确调用 close())。

  • 原因

    • 代码 Bug:未关闭 Socket(如 Java 未调用 socket.close())。

    • 线程阻塞:处理请求时卡住,无法执行关闭逻辑。

  • 解决

    • 检查代码确保资源释放(try-with-resources 或 finally 块)。

    • 优化服务端性能(避免阻塞)。

2.3什么情况下syn请求丢弃,失效?如何分析,如何解决,不考虑防火墙

(1)SYN 被丢弃的原因

  • 半连接队列(SYN Queue)满

    • 服务端未及时处理 SYN,导致队列溢出(默认大小 net.ipv4.tcp_max_syn_backlog)。

  • SYN Flood 攻击

    • 攻击者发送大量 SYN 但不完成握手,耗尽服务端资源。

  • 网络问题

    • 中间路由器丢弃 SYN(如拥塞、TTL 过期)。

(2)如何分析?

  • 服务端统计

  • 抓包分析

(3)解决方案

  • 增大半连接队列

  • 启用 SYN Cookie(防攻击):

  • 优化服务端

    • 加快握手处理(如负载均衡、扩容)。

总结

问题原因解决方案
TIME_WAIT 过多短连接频繁关闭复用连接、调整 tcp_tw_reuse
CLOSE_WAIT 过多服务端未正确关闭 Socket检查代码、优化资源释放
SYN 被丢弃队列满、攻击、网络问题增大队列、SYN Cookie、抓包分析

3.项目深挖,包括项目实现背景(即为什么去做这个项目),项目功能如何实现,项目实现中的一些细节和设计模式,项目对应功能如何测试,如何部署。遇到问题如何发散解决(40min)

3.进程线程区别

对比项进程(Process)线程(Thread)
定义操作系统资源分配的基本单位CPU 调度的基本单位(属于进程)
内存占用独立内存空间(隔离性强)共享进程内存(高效但需同步)
创建开销大(需分配独立资源)小(共享进程资源)
通信方式进程间通信(IPC):管道、共享内存、消息队列直接读写共享变量(需加锁)
崩溃影响一个进程崩溃不影响其他进程一个线程崩溃可能导致整个进程退出
并发性多进程并行(多核)多线程并行(轻量级并发)

关键点

  • 线程是进程的子任务,共享进程的堆内存,但有自己的栈和寄存器。

  • 多线程需处理竞态条件(如 synchronizedReentrantLock)。

4OSI七层模型

层数名称功能协议/设备
7应用层用户接口(HTTP、FTP)HTTP、SMTP、DNS
6表示层数据格式转换(加密、压缩)SSL、JPEG
5会话层建立/管理会话(RPC)NetBIOS
4传输层端到端可靠传输(TCP/UDP)TCP、UDP
3网络层路由寻址(IP 地址)IP、ICMP、路由器
2数据链路层帧传输(MAC 地址)Ethernet、交换机
1物理层比特流传输(电缆、光纤)网卡、集线器

简化记忆

  • 上三层(应用、表示、会话):面向用户。

  • 下四层(传输、网络、数据链路、物理):面向数据。

5详细介绍线程

线程的生命周期(状态)

  1. NEW:刚创建,未调用 start()

  2. RUNNABLE:可运行(可能在等待 CPU)。

  3. BLOCKED:等待锁(如 synchronized)。

  4. WAITING:无限期等待(如 wait())。

  5. TIMED_WAITING:超时等待(如 sleep(1000))。

  6. TERMINATED:执行完毕。

创建线程的方式

  1. 继承 Thread 类

  2. 实现 Runnable 接口:

  3. 线程池ExecutorService):

线程同步

  • synchronized

  • ReentrantLock

1.get和post的区别

1. GET vs POST 的区别

对比项GETPOST
语义获取资源(幂等)提交数据(非幂等)
数据位置URL 查询参数(明文)请求体(可加密)
长度限制受 URL 长度限制(约 2KB)无限制(服务器可配置)
缓存可被缓存不可缓存
安全性参数暴露在 URL(不安全)数据在请求体中(相对安全)

使用场景

  • GET:搜索、分页(如 ?page=1)。

  • POST:登录、表单提交(如 JSON 数据)。

5.互联网这两年前景不好,谈一下你的看法

  • 短期挑战

    • 政策监管加强(如数据安全、反垄断)。

    • 资本趋于理性,野蛮增长时代结束。

    • 全球经济下行影响投资和消费。

  • 长期机会

    • 技术驱动:AI、云计算、物联网等仍是未来核心。

    • 数字化转型:传统行业(医疗、制造)仍需互联网技术赋能。

    • 全球化市场:中国互联网企业出海(如 TikTok、SHEIN)。

结论:行业从“高速增长”转向“高质量发展”,对技术深度和复合能力要求更高。

6.为什么觉着互联网会比其他行业就业广

  1. 技术渗透性强

    • 几乎所有行业都需要互联网技术(金融→FinTech、零售→电商)。

  2. 岗位多样性

    • 技术(开发、测试)、产品、运营、设计、数据分析等岗位覆盖全链条。

  3. 薪资竞争力

    • 平均薪资高于传统行业(如制造业)。

  4. 低准入门槛

    • 相比医生、律师等职业,互联网更依赖技能而非学历证书。

  5. 远程办公机会

    • 支持全球化协作(如程序员可远程为海外公司工作)。

7.app测试和web测试有何不同

对比项App 测试Web 测试
运行环境移动设备(iOS/Android)浏览器(Chrome、Firefox)
兼容性需测试不同机型、OS版本、分辨率主要测试浏览器兼容性
网络依赖弱网、断网测试更重要网络影响较小
安装与更新需测试安装、升级、卸载流程无需安装,即时更新
性能指标内存占用、CPU、电量、启动速度页面加载速度、服务器响应时间
工具Appium、XCUITest、EspressoSelenium、Cypress、Playwright

核心差异

  • App 测试更关注硬件交互(如摄像头、GPS)和移动端特性(如手势操作)。

  • Web 测试更注重跨浏览器一致性和前端渲染性能。

8.你是怎么区分前端和后端的

对比项前端(Frontend)后端(Backend)
职责用户界面(UI)和交互逻辑数据处理、业务逻辑、数据库交互
技术栈HTML/CSS/JavaScript、React/VueJava/Python/Go、Spring/Django
关注点用户体验、页面性能、兼容性高并发、安全性、API 设计
调试工具Chrome DevTools、LighthousePostman、Jmeter、日志分析
输出结果浏览器渲染的页面数据库记录、API 响应(JSON/XML)

简单判断

  • 前端代码运行在浏览器,后端代码运行在服务器

  • 前端请求数据(如 fetch('/api/data')),后端提供数据(如返回 JSON)。

内存分页与分段的区别及优缺点

分页(Paging)

  • 原理

    • 内存划分为固定大小的页(如 4KB),进程的地址空间分为同等大小的页框。

    • 通过页表映射虚拟地址到物理地址。

  • 优点

    • 解决外部碎片(物理内存利用率高)。

    • 支持虚拟内存(页面可换入换出磁盘)。

  • 缺点

    • 页内可能产生内部碎片(最后一页未用满)。

分段(Segmentation)

  • 原理

    • 按逻辑单元(代码段、数据段、堆栈段)划分内存,每段长度可变。

    • 通过段表记录基址和长度。

  • 优点

    • 符合程序逻辑(便于共享和保护段)。

  • 缺点

    • 产生外部碎片(需内存紧凑或动态分区)。

对比总结

特性分页分段
划分单位固定大小页可变长度段
碎片问题内部碎片外部碎片
管理复杂度简单(页表)复杂(段表+保护机制)
适用场景通用内存管理(OS 主流方案)需要逻辑隔离(如早期系统)

现代 OS(如 Linux):结合分页和分段,实际使用分页机制,段基址固定为 0。

Android方向

四大组件生命周期(Activity、Service等)

(1) Activity 生命周期

  • 核心方法

    • onCreate():初始化 UI 和数据。

    • onStart():Activity 可见但未前台交互。

    • onResume():Activity 进入前台,可交互。

    • onPause():失去焦点(如弹窗),需快速释放资源。

    • onStop():完全不可见(可能被销毁)。

    • onDestroy():释放所有资源。

  • 场景

    • 屏幕旋转:onDestroy() → onCreate()(默认重建)。

    • 按 Home 键:onPause() → onStop()

(2) Service 生命周期

  • 启动方式

    • startService()

      • onCreate() → onStartCommand() → (运行中)→ onDestroy()

    • bindService()

      • onCreate() → onBind() → (通信中)→ onUnbind() → onDestroy()

(3) BroadcastReceiver

  • 动态注册

    • onReceive() 执行后立即销毁。

  • 静态注册

    • 常驻,通过 AndroidManifest.xml 声明。

(4) ContentProvider

  • 生命周期由系统管理,主要方法:

    • onCreate():初始化数据源(如数据库)。

    • query()/insert()/update()/delete():CRUD 操作。

Handler机制原理(Looper、MessageQueue)

核心组件

  1. Handler:发送和处理消息(sendMessage() / handleMessage())。

  2. MessageQueue:消息队列(单链表,按时间排序)。

  3. Looper:循环从 MessageQueue 取消息并分发。

 

工作流程

  1. Looper.prepare():创建 Looper 和 MessageQueue(主线程已默认创建)。

  2. Looper.loop():无限循环调用 MessageQueue.next() 获取消息。

  3. Handler.sendMessage():将 Message 插入 MessageQueue

  4. Handler.handleMessage():在目标线程处理消息。

性能优化:内存泄漏(Cursor未关闭、Bitmap未回收)、ANR原因

自定义View流程(measure/layout/draw)

iOS方向

Runtime机制:消息转发、Category实现

消息转发

Objective-C 的消息转发机制是在对象无法响应某个方法时提供的一种补救措施。消息转发分为三个阶段:

  1. 动态方法解析+resolveInstanceMethod: 或 +resolveClassMethod:,可以在这里动态添加方法实现。

  2. 备用接收者-forwardingTargetForSelector:,可以将消息转发给其他对象处理。

  3. 完整转发-methodSignatureForSelector: 和 -forwardInvocation:,可以封装 NSInvocation 进行更灵活的转发。

Category 实现

Category 是通过运行时动态将方法添加到类中(编译时为类生成 category_t 结构体,运行时合并到类的方法列表中)。特点:

  • 可以添加方法,但不能添加实例变量(可通过关联对象间接实现)。

  • 方法会覆盖原类方法(同名方法调用优先级:Category > 原类 > 父类)。

实现原理:

  • 编译后生成 _category_t 结构体,包含方法、属性、协议列表。

  • 运行时通过 attachCategories 函数将 Category 数据合并到类中。

多线程:GCD与NSOperation对比、线程安全

特性GCD (Grand Central Dispatch)NSOperation
抽象层级C API,更底层Objective-C 对象,更高层
任务封装BlockNSOperation 子类
依赖管理需手动控制(如 barrier)直接通过 addDependency: 支持
状态控制无直接状态管理可监听 isReady/isFinished/isCancelled
优先级通过 QoS 设置可设置 queuePriority
取消任务不可取消可取消
适用场景简单异步任务复杂任务依赖关系

线程安全

保证线程安全的常见方式:

  1. 串行队列:将读写操作放到同一队列(如 dispatch_queue_serial)。

  2. @synchronizedNSLockos_unfair_lockpthread_mutex

  3. 原子操作atomic 属性(仅保证读写原子性,不保证线程安全)。

  4. 内存屏障OSMemoryBarrier 避免指令重排。

设计模式:Delegate vs Notification vs KVO的差异及应用场景

特性DelegateNotificationKVO
通信方向一对一(反向传值)一对多(广播)一对多(监听属性变化)
耦合度较高(需协议绑定)低(松散耦合)最低(无需显式调用)
实现复杂度中(需实现协议方法)低(仅注册观察)高(需处理移除观察者)
适用场景UITableView 事件处理跨模块通信(如登录状态广播)数据模型变化监听(如进度更新)
性能开销低(直接调用)中(需维护观察者列表)高(依赖 Runtime 派发)

最佳实践

  • 需要返回值时用 Delegate。

  • 跨组件通信用 Notification。

  • 监听对象属性变化用 KVO(注意移除观察者避免崩溃)。

单例模式的实现与优缺点

优点

  1. 全局唯一访问点,便于管理资源(如配置、缓存)。

  2. 减少重复实例化开销。

缺点

  1. 测试困难:全局状态可能导致测试依赖。

  2. 内存常驻:单例生命周期与应用一致。

  3. 隐藏耦合:滥用会导致代码难以维护。

替代方案:依赖注入(通过参数传递实例)。

MVC/MVVM在Android中的实践

MVC

  • Model:数据层(Room、Retrofit)。

  • View:XML 布局文件。

  • Controller:Activity/Fragment(实际中常承担过多逻辑)。

问题:Activity 臃肿,单元测试困难。

MVVM(推荐)

  • ViewModel:持有数据,暴露 LiveData/Flow。

  • View:Activity/Fragment 观察数据变化。

  • Data Binding:可选的 XML 绑定(减少样板代码)。

 

 

http://www.xdnf.cn/news/15473.html

相关文章:

  • 【PCIe 总线及设备入门学习专栏 5.1.2 -- PCIe EP core_rst_n 与 app_rst_n】
  • Java 大视界 -- Java 大数据机器学习模型在金融风险传染路径分析与防控策略制定中的应用(347)
  • HTML网页结构(基础)
  • 使用Spring Cloud LoadBalancer报错java.lang.IllegalStateException
  • Nestjs框架: 数据库架构设计与 NestJS 多 ORM 动态数据库应用与连接池的配置
  • QTableView鼠标双击先触发单击信号
  • 项目进度与预算脱节,如何进行同步管理
  • 从0开始学习R语言--Day47--Nomogram
  • 多租户SaaS系统中设计安全便捷的跨租户流程共享
  • 文心一言开源版部署及多维度测评实例
  • 深度解析 AI 提示词工程(Prompt Engineering)
  • 【YOLOv11-目标检测】06-模型部署(C++)
  • 可微分3D高斯溅射(3DGS)在医学图像三维重建中的应用
  • gRPC实战指南:像国际快递一样调用跨语言服务 —— 解密Protocol Buffer与HTTP/2的完美结合
  • AI 增强大前端数据加密与隐私保护:技术实现与合规遵
  • 20250715武汉xx公司面试一面
  • Springboot儿童认知图文辅助系统6yhkv(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • React.FC与React.Component
  • 高并发四种IO模型的底层原理
  • [Dify]--进阶3-- 如何通过插件扩展 Dify 的功能能力
  • 深入浅出 RabbitMQ-核心概念介绍与容器化部署
  • ubuntu部署kvm
  • Linux操作系统从入门到实战(十)Linux开发工具(下)make/Makefile的推导过程与扩展语法
  • OpenCSG QA:您的国产大模型与 Agent 管理平台
  • 运维技术教程之Jenkins上的known_hosts文件
  • 渲染设计图的空间革命:可视化技术如何重塑设计决策
  • Keepalived双机热备概述
  • 2025华为ODB卷-IPv4地址转换成整数三语言题解
  • DOM入门知识
  • 回顾一下Docker的基本操作