应届毕业生计算机专业常见面试题

应届毕业生计算机专业常见面试题

一、Java 基础

1.1 基本概念

Q:Java 中 == 和 equals 的区别?

  • == 比较的是引用地址(基本类型比较值)
  • equals 比较的是对象内容(默认行为同 ==String 等类已重写)
String a = new String("hello");
String b = new String("hello");
a == b;       // false,不同对象
a.equals(b);  // true,内容相同

Q:String、StringBuilder、StringBuffer 的区别?

对比项StringStringBuilderStringBuffer
可变性不可变可变可变
线程安全安全(不可变)不安全安全(synchronized)
性能拼接时产生大量临时对象最快略慢于 StringBuilder
使用场景少量字符串操作单线程大量拼接多线程大量拼接

Q:final、finally、finalize 的区别?

  • final:修饰类不可继承,修饰方法不可重写,修饰变量不可再赋值
  • finally:try-catch-finally 中无论是否异常都会执行的代码块(除 JVM 退出或线程被杀)
  • finalize:Object 类的方法,GC 回收前调用(Java 9 已标记废弃,不推荐依赖)

Q:重载(Overload)和重写(Override)的区别?

对比项重载重写
发生范围同一个类子类与父类
方法名相同相同
参数列表必须不同必须相同
返回值可不同相同或协变
访问修饰符可不同不能更严格

1.2 集合框架

Q:ArrayList 和 LinkedList 的区别?

对比项ArrayListLinkedList
底层结构动态数组双向链表
随机访问O(1)O(n)
头部插入/删除O(n)O(1)
尾部插入均摊 O(1)O(1)
内存占用紧凑每个节点额外存储前后指针
扩容机制1.5 倍扩容无需扩容

Q:HashMap 的底层原理?

核心结构:数组 + 链表 + 红黑树(JDK 8)

put 流程:
  1. 计算 key 的 hash 值,通过 (n - 1) & hash 定位桶位置
  2. 桶为空 → 直接放入
  3. 桶不为空 → 遍历链表
     a. key 已存在 → 覆盖旧值
     b. key 不存在 → 尾插法添加
     c. 链表长度 >= 8 且数组长度 >= 64 → 转为红黑树
  4. size > threshold(容量 × 负载因子 0.75)→ 扩容为 2 倍

Q:HashMap 为什么线程不安全?

  • JDK 7:多线程扩容时可能产生环形链表,导致死循环
  • JDK 8:多线程 put 时可能丢失数据、覆盖已有值

Q:ConcurrentHashMap 是如何保证线程安全的?

  • JDK 7:Segment 数组 + HashEntry,每个 Segment 是一把锁(分段锁)
  • JDK 8:CAS + synchronized,锁粒度从 Segment 级别降为桶(首节点)级别

1.3 多线程

Q:线程的创建方式?

  1. 继承 Thread 类,重写 run()
  2. 实现 Runnable 接口
  3. 实现 Callable<V> 接口(有返回值,配合 Future)
  4. 线程池 ExecutorService(推荐)

Q:synchronized 和 ReentrantLock 的区别?

对比项synchronizedReentrantLock
锁类型JVM 层面(monitorenter)API 层面(java.util.concurrent)
是否可中断不可中断lockInterruptibly() 可中断
是否公平锁非公平支持公平/非公平
条件绑定单一条件(wait/notify)多条件(Condition)
释放锁自动释放(作用域结束)必须 unlock()(finally 中释放)

Q:volatile 关键字的作用?

两个作用:

  1. 可见性:修改后立即刷新到主内存,其他线程读取时从主内存获取
  2. 禁止指令重排序:通过内存屏障防止编译器和 CPU 重排

不保证原子性,i++ 仍需要加锁或使用 AtomicInteger

Q:线程池的核心参数?

ThreadPoolExecutor(
    int corePoolSize,        // 核心线程数
    int maximumPoolSize,     // 最大线程数
    long keepAliveTime,      // 非核心线程空闲存活时间
    TimeUnit unit,           // 时间单位
    BlockingQueue<Runnable> workQueue,  // 任务队列
    ThreadFactory threadFactory,         // 线程工厂
    RejectedExecutionHandler handler     // 拒绝策略
)

任务提交流程

提交任务
  → 核心线程未满?创建核心线程执行
  → 核心线程已满,队列未满?入队
  → 队列已满,最大线程未满?创建非核心线程执行
  → 最大线程已满?执行拒绝策略

四种拒绝策略:AbortPolicy(抛异常)、CallerRunsPolicy(调用者执行)、DiscardPolicy(丢弃)、DiscardOldestPolicy(丢弃队列最老任务)

1.4 JVM

Q:JVM 内存模型(运行时数据区)?

┌─────────────────────────────────────┐
│              方法区(元空间)          │  ← 类信息、常量、静态变量
│         Metaspace(JDK 8+)         │
├─────────────────────────────────────┤
│               堆                    │  ← 对象实例、数组(GC 主要区域)
│            Heap                     │     年轻代 + 老年代
├──────────────────┬──────────────────┤
│   虚拟机栈       │   本地方法栈     │  ← 方法调用、局部变量表
│   VM Stack      │   Native Stack   │
├──────────────────┴──────────────────┤
│              程序计数器              │  ← 当前线程执行的字节码行号
│         Program Counter             │
└─────────────────────────────────────┘

其中堆和方法区是所有线程共享的,虚拟机栈、本地方法栈、程序计数器是线程私有的。

Q:垃圾回收算法?

算法原理优缺点
标记-清除标记存活对象,清除未标记的简单,但产生内存碎片
标记-整理标记后存活对象向一端移动无碎片,但移动开销大
复制算法将存活对象复制到另一半空间无碎片,但浪费一半空间

常见垃圾收集器

  • CMS:以最短回收停顿为目标,标记-清除算法(老年代)
  • G1:将堆划分为多个 Region,可预测停顿时间(JDK 9 默认)
  • ZGC:超低停顿(< 1ms),JDK 11 引入,JDK 15 正式可用

二、数据库

2.1 MySQL 基础

Q:InnoDB 和 MyISAM 的区别?

对比项InnoDBMyISAM
事务支持不支持
锁粒度行锁表锁
外键支持不支持
崩溃恢复支持(redo log)不支持
全文索引支持但效果一般支持
MVCC支持不支持
count(*)不缓存,需遍历索引缓存,速度快
默认引擎MySQL 5.5+ 默认早期默认

Q:索引的类型?

  • 主键索引:唯一且非空,一张表只能有一个
  • 唯一索引:值唯一,允许 NULL
  • 普通索引:最基本的索引,无限制
  • 组合索引:多个列组合(遵循最左前缀匹配原则)
  • 全文索引:用于文本搜索

Q:什么情况下索引会失效?

  1. 对索引列使用函数:WHERE YEAR(create_time) = 2024
  2. 隐式类型转换:WHERE phone = 13800138000(phone 是字符串类型)
  3. 违反最左前缀原则:组合索引 (a, b, c),只查 b, c
  4. 使用 OR 连接非索引列
  5. LIKE 以通配符开头:WHERE name LIKE '%abc'
  6. WHERE 中对索引列做运算:WHERE id + 1 = 10
  7. 优化器判断全表扫描更快时(如数据量极小或区分度极低)

Q:事务的四大特性(ACID)?

特性含义实现机制
原子性(Atomicity)事务是不可分割的最小操作单元undo log
一致性(Consistency)数据从一个一致状态到另一个一致状态AID + 应用层约束
隔离性(Isolation)并发事务之间互不影响MVCC + 锁
持久性(Durability)事务提交后数据永久保存redo log

Q:MySQL 的隔离级别?

隔离级别脏读不可重复读幻读
读未提交(Read Uncommitted)
读已提交(Read Committed)
可重复读(Repeatable Read)有(InnoDB 通过 MVCC+间隙锁基本解决)
串行化(Serializable)

MySQL 默认隔离级别:可重复读(Repeatable Read)

Q:MVCC 的原理?

MVCC(多版本并发控制)通过每行数据的隐藏列 + undo log 实现无锁读:

  • DB_TRX_ID:最近修改该行的事务 ID
  • DB_ROLL_PTR:指向 undo log 中的旧版本
  • DB_ROW_ID:隐藏主键

ReadView 判断版本可见性:

创建 ReadView 时记录:
  m_ids:活跃事务 ID 列表
  min_trx_id:最小活跃事务 ID
  max_trx_id:下一个将分配的事务 ID

判断规则:
  trx_id < min_trx_id → 可见(事务已提交)
  trx_id >= max_trx_id → 不可见(事务在 ReadView 之后开始)
  min_trx_id <= trx_id < max_trx_id → 不在 m_ids 中则可见

2.2 SQL 优化

Q:如何进行 SQL 优化?

  1. 通过 EXPLAIN 查看执行计划,关注 typekeyrowsExtra
  2. 避免 SELECT *,只查需要的列
  3. 合理使用索引,避免索引失效
  4. 避免 IN 子查询中的大量数据,可用 JOIN 替代
  5. 分页查询优化:大偏移量时用 WHERE id > last_id LIMIT n 替代 LIMIT offset, n
  6. 避免在 WHERE 中对列做函数运算

Q:EXPLAIN 中 type 字段的含义(从好到差)?

system > const > eq_ref > ref > range > index > ALL
  • const:主键或唯一索引等值查询,最多一条
  • eq_ref:JOIN 时使用主键或唯一索引关联
  • ref:普通索引等值查询
  • range:索引范围扫描(BETWEEN、>、<)
  • index:全索引扫描
  • ALL:全表扫描(最差)

三、计算机网络

3.1 TCP/IP

Q:三次握手的过程?

客户端                          服务器
  │                               │
  │──── SYN(seq=x)─────────────>│  第一次:客户端发送连接请求
  │                               │
  │<─── SYN+ACK(seq=y,ack=x+1)──│  第二次:服务器确认并发起连接
  │                               │
  │──── ACK(ack=y+1)──────────>│  第三次:客户端确认服务器的连接
  │                               │
  │═══ 连接建立,开始传输数据 ═════│

为什么需要三次握手?

  • 确认双方的发送和接收能力都正常
  • 防止已失效的连接请求报文突然到达服务器,造成资源浪费

Q:四次挥手的过程?

客户端(主动关闭)              服务器(被动关闭)
  │                               │
  │──── FIN(seq=u)─────────────>│  第一次:客户端发送关闭请求
  │                               │
  │<─── ACK(ack=u+1)────────────│  第二次:服务器确认
  │                               │  (服务器仍可发送数据)
  │                               │
  │     ... 服务器继续发送数据 ...  │
  │                               │
  │<─── FIN(seq=w)─────────────│  第三次:服务器也发送关闭请求
  │                               │
  │──── ACK(ack=w+1)──────────>│  第四次:客户端确认
  │                               │
  │  等待 2MSL 后关闭              │

为什么需要四次挥手?

  • TCP 是全双工的,每个方向都需要单独关闭
  • 服务器收到 FIN 后可能还有数据未发送完,所以先回 ACK,等数据发完再发 FIN

Q:TIME_WAIT 状态的作用?

存在时间:2MSL(Maximum Segment Lifetime,约 1~4 分钟)

作用:

  1. 确保最后一个 ACK 能到达服务器(如果丢失,服务器会重发 FIN)
  2. 让本连接的所有报文在网络中消失,避免影响新连接

Q:TCP 如何保证可靠传输?

  1. 校验和:检测数据传输中的位错误
  2. 序列号:保证数据有序,接收方按序重组
  3. 确认应答(ACK):确认已收到的数据
  4. 超时重传:发送后未收到 ACK,在超时后重传
  5. 流量控制(滑动窗口):接收方通过窗口大小控制发送速率
  6. 拥塞控制(慢启动、拥塞避免、快速重传、快速恢复):防止网络过载

Q:拥塞控制和流量控制的区别?

对比项流量控制拥塞控制
目的保护接收方不被淹没防止网络过载
控制方接收方(通过窗口大小)发送方(通过拥塞窗口)
机制滑动窗口慢启动、拥塞避免等

3.2 HTTP

Q:HTTP 和 HTTPS 的区别?

对比项HTTPHTTPS
端口80443
安全性明文传输TLS/SSL 加密传输
证书不需要需要 CA 证书
速度略快略慢(握手开销)

Q:HTTP 常见状态码?

  • 200 OK:请求成功
  • 301 Moved Permanently:永久重定向
  • 302 Found:临时重定向
  • 304 Not Modified:缓存未过期
  • 400 Bad Request:请求参数错误
  • 401 Unauthorized:未认证
  • 403 Forbidden:无权限
  • 404 Not Found:资源不存在
  • 500 Internal Server Error:服务器内部错误
  • 502 Bad Gateway:网关错误
  • 503 Service Unavailable:服务不可用

Q:GET 和 POST 的区别?

对比项GETPOST
参数位置URL 中请求体中
缓存可被缓存不可缓存
安全性参数暴露在 URL参数在请求体,相对安全
参数长度受 URL 长度限制理论上无限制
幂等性幂等非幂等
浏览器回退无害会提示重新提交

Q:Cookie 和 Session 的区别?

对比项CookieSession
存储位置客户端浏览器服务器端
大小限制4KB 左右无大小限制
安全性可被篡改、窃取相对安全
生命周期可设置过期时间默认浏览器关闭失效
跨域同域下自动携带通过 Cookie 中的 SessionID 关联

四、操作系统

Q:进程和线程的区别?

对比项进程线程
定义资源分配的基本单位CPU 调度的基本单位
地址空间独立共享所属进程的地址空间
通信方式管道、消息队列、共享内存等共享内存(同一进程内)
创建/切换开销
健壮性一个进程崩溃不影响其他进程一个线程崩溃可能导致整个进程崩溃

Q:进程间通信方式?

  1. 管道(Pipe):半双工,父子进程间使用
  2. 命名管道(FIFO):无亲缘关系的进程间通信
  3. 消息队列:消息链表,有格式的消息传递
  4. 共享内存:最快的方式,需要同步机制(信号量)
  5. 信号量(Semaphore):控制共享资源的访问
  6. 信号(Signal):异步通知,如 kill -9
  7. Socket:可用于不同主机间的通信

Q:死锁的四个必要条件?如何预防?

必要条件(同时满足才会死锁):

  1. 互斥:资源一次只能被一个进程使用
  2. 占有并等待:持有资源的同时等待其他资源
  3. 不可抢占:已获得的资源不能被强行夺走
  4. 循环等待:进程之间形成循环等待资源的关系

预防策略:

  • 破坏互斥 → 难以实现(某些资源本身就是互斥的)
  • 破坏占有并等待 → 一次性申请所有资源
  • 破坏不可抢占 → 获取不到资源时主动释放已有资源
  • 破坏循环等待 → 资源编号排序,按序申请

五、数据结构与算法

5.1 常见排序算法

算法平均时间最坏时间空间稳定性
冒泡排序O(n²)O(n²)O(1)稳定
选择排序O(n²)O(n²)O(1)不稳定
插入排序O(n²)O(n²)O(1)稳定
快速排序O(n log n)O(n²)O(log n)不稳定
归并排序O(n log n)O(n log n)O(n)稳定
堆排序O(n log n)O(n log n)O(1)不稳定

面试高频:手写快排

public void quickSort(int[] arr, int left, int right) {
    if (left >= right) return;
    int pivot = partition(arr, left, right);
    quickSort(arr, left, pivot - 1);
    quickSort(arr, pivot + 1, right);
}

private int partition(int[] arr, int left, int right) {
    int pivot = arr[right];
    int i = left;
    for (int j = left; j < right; j++) {
        if (arr[j] < pivot) {
            swap(arr, i, j);
            i++;
        }
    }
    swap(arr, i, right);
    return i;
}

5.2 常考算法题型

题型代表题目关键思路
二分查找在有序数组中查找目标值左闭右开区间,注意边界条件
链表反转链表、判断环、合并有序链表虚拟头节点、快慢指针
二叉树前中后序遍历、层序遍历、最近公共祖先递归、BFS/DFS
动态规划最长子序列、背包问题、爬楼梯定义 dp 数组、找状态转移方程
滑动窗口最长无重复子串、最小覆盖子串双指针维护窗口
回溯全排列、组合、N 皇后做选择 → 递归 → 撤销选择

5.3 时间复杂度速记

O(1)         < O(log n)      < O(n)          < O(n log n)
常数时间        对数时间        线性时间          线性对数

O(n²)        < O(n³)         < O(2ⁿ)         < O(n!)
平方时间        立方时间        指数时间          阶乘时间

六、Spring 框架

Q:Spring IoC 的原理?

IoC(控制反转)将对象的创建和管理从代码内部转移到 Spring 容器。

  • BeanFactory:基础容器,懒加载
  • ApplicationContext:扩展容器,启动时预加载所有 Bean

Bean 的生命周期:

实例化 → 属性注入(依赖注入)→ Aware 接口回调
→ BeanNameAware / BeanFactoryAware
→ BeanPostProcessor.postProcessBeforeInitialization
→ InitializingBean.afterPropertiesSet
→ 自定义 init-method
→ BeanPostProcessor.postProcessAfterInitialization
→ 使用
→ DisposableBean.destroy / 自定义 destroy-method

Q:Spring AOP 的原理?

AOP(面向切面编程)将横切逻辑(日志、事务、权限)从业务代码中分离。

实现方式:

  • JDK 动态代理:基于接口,使用 Proxy.newProxyInstance(),目标类必须实现接口
  • CGLIB 代理:基于继承,生成目标类的子类,不能代理 final 方法

Spring 默认策略:有接口用 JDK 代理,无接口用 CGLIB 代理。

Q:Spring 事务 @Transactional 在什么情况下会失效?

  1. 方法不是 public
  2. 方法是 finalstatic
  3. 同一个类中方法内部调用(未经过代理)
  4. 异常被 catch 吞掉,未重新抛出
  5. 抛出了非 RuntimeException(默认只回滚 RuntimeException 和 Error)
  6. 数据库引擎不支持事务(如 MyISAM)

Q:Spring Boot 自动装配的原理?

核心注解 @SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan

@EnableAutoConfiguration
  → @Import(AutoConfigurationImportSelector.class)
    → 读取 META-INF/spring.factories(Spring Boot 2.x)
    或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Spring Boot 3.x)
      → 加载自动配置类
        → 根据 @Conditional 系列注解判断是否生效
          → @ConditionalOnClass(类路径存在某类)
          → @ConditionalOnProperty(配置文件存在某属性)
          → @ConditionalOnMissingBean(容器中不存在某 Bean)

七、Redis

Q:Redis 常见的数据结构?

数据类型底层实现常见应用场景
StringSDS(Simple Dynamic String)缓存、计数器、分布式锁
Hash哈希表 + 压缩列表存储对象、购物车
List双向链表 + 压缩列表消息队列、最新列表
Set哈希表去重、标签、共同好友
ZSet跳表 + 哈希表排行榜、延时队列

Q:Redis 的持久化机制?

方式RDB(快照)AOF(追加日志)
原理定时将内存数据快照写入磁盘记录每次写操作命令
文件dump.rdbappendonly.aof
恢复速度快(直接加载文件)慢(重放所有命令)
数据安全性可能丢失最后一次快照后的数据更安全(每秒刷盘最多丢 1 秒)
文件大小小(二进制压缩)
适用场景备份、灾难恢复数据安全要求高的场景

Q:缓存穿透、缓存击穿、缓存雪崩的区别和解决方案?

问题原因解决方案
缓存穿透查询不存在的数据,缓存和数据库都没有布隆过滤器、缓存空值、参数校验
缓存击穿热点 Key 过期,大量请求打到数据库互斥锁、热点数据永不过期(逻辑过期)
缓存雪崩大量 Key 同时过期,或 Redis 宕机过期时间加随机值、搭建高可用集群、限流降级

Q:Redis 如何实现分布式锁?

# 加锁(SETNX + 过期时间,保证原子性)
SET lock_key unique_value NX PX 30000

# 释放锁(Lua 脚本,保证原子性)
if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
else
    return 0
end

关键点:必须设置过期时间(防止死锁)、释放时校验值(防止误删)、使用 Lua 脚本保证原子性。

更完善的方案:Redisson(看门狗机制自动续期)。


八、常见设计题

8.1 手写代码题

反转单链表

public ListNode reverseList(ListNode head) {
    ListNode prev = null, curr = head;
    while (curr != null) {
        ListNode next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }
    return prev;
}

LRU 缓存

class LRUCache {
    private int capacity;
    private Map<Integer, Node> map;
    private Node head, tail; // 双向链表的头尾哨兵

    public LRUCache(int capacity) {
        this.capacity = capacity;
        map = new HashMap<>();
        head = new Node(); tail = new Node();
        head.next = tail; tail.prev = head;
    }

    public int get(int key) {
        if (!map.containsKey(key)) return -1;
        Node node = map.get(key);
        removeToHead(node); // 移到链表头部
        return node.val;
    }

    public void put(int key, int value) {
        if (map.containsKey(key)) {
            map.get(key).val = value;
            removeToHead(map.get(key));
        } else {
            if (map.size() >= capacity) {
                map.remove(tail.prev.key); // 移除链表尾部
                removeNode(tail.prev);
            }
            Node node = new Node(key, value);
            map.put(key, node);
            addToHead(node);
        }
    }
}

8.2 场景设计题

Q:设计一个短链服务?

核心思路:长 URL → 哈希/发号器 → 短码 → 存数据库 → 重定向

长 URL → MD5(长URL) → 取前 6~8 位作为短码(处理冲突)
       或发号器自增 ID → Base62 编码 → 短码

存储:短码 → 长URL 的映射(数据库 + 缓存)
访问:短码 → 查缓存 → 查数据库 → 302 重定向到长 URL

Q:如何设计一个秒杀系统?

核心挑战:短时间内大量请求,库存有限。

前端:按钮防重复点击、验证码、请求限流
网关:令牌桶限流
缓存层:
  - 库存预扣减(Redis DECR)
  - 用户去重(SET 防止重复下单)
消息队列:
  - 削峰填谷,将请求异步化
  - 下单请求进入 MQ,消费者依次处理
数据库:
  - 订单表:最终一致性
  - 库存表:乐观锁(UPDATE stock SET count = count - 1 WHERE id = ? AND count > 0)

九、面试软技能

9.1 自我介绍模板

面试官您好,我是 XX 学校计算机专业的应届毕业生。在校期间我主要学习了 Java 后端开发,熟悉 Spring Boot、MySQL、Redis 等技术栈。实习期间在 XX 公司负责 XX 模块的开发,使用了 XX 技术解决了 XX 问题。我的毕业设计是 XX,主要实现了 XX 功能。我对技术有持续的热情,希望能加入贵公司。

关键点:控制在 2 分钟以内,突出项目经验技术亮点

9.2 常见 HR 问题

问题回答要点
你的优缺点?优点结合技术能力,缺点说真实但可控的(如"有时过于关注细节")
为什么选择我们公司?结合公司业务和自身职业规划
你的职业规划?1~3 年深耕技术,3~5 年向架构/技术管理发展
最大的挑战/收获?具体项目场景 + 解决过程 + 反思总结
你有什么问题想问?问团队技术栈、工作流程、新人培养机制

十、总结

应届生面试的知识图谱:

计算机基础
├── Java 基础
│   ├── 集合框架(HashMap、ConcurrentHashMap)
│   ├── 多线程(synchronized、volatile、线程池)
│   └── JVM(内存模型、GC 算法)
├── 数据库
│   ├── MySQL(索引、事务、MVCC)
│   └── SQL 优化(EXPLAIN)
├── 计算机网络
│   ├── TCP/UDP(三次握手、四次挥手)
│   └── HTTP/HTTPS(状态码、缓存)
├── 操作系统
│   ├── 进程与线程
│   └── 死锁
├── 数据结构与算法
│   ├── 排序算法
│   ├── 链表、二叉树
│   └── 动态规划、滑动窗口
├── 框架
│   ├── Spring(IoC、AOP、事务)
│   └── Spring Boot(自动装配)
├── Redis
│   ├── 数据结构
│   ├── 持久化
│   └── 缓存问题(穿透、击穿、雪崩)
└── 设计题
    ├── 手写代码(链表、LRU)
    └── 场景设计(短链、秒杀)

建议按广度优先的策略准备,先覆盖所有常见知识点,再对高频考点深入理解。刷 LeetCode 时重点攻克链表、二叉树、动态规划三大类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值