JavaDeveloperBrain
JavaDeveloperBrain copied to clipboard
[Java工程师必备+学习+知识点+面试]:包含计算机网络知识、JavaSE、JVM、Spring、Springboot、SpringCloud、Mybatis、多线程并发、netty、MySQL、MongoDB、Elasticsearch、Redis、HBASE、RabbitMQ、RocketMQ、Pulsar...
JavaDeveloperBrain
[Java工程师必备+学习+知识点+面试]:包含计算机网络知识、JavaSE、JVM、Spring、Springboot、SpringCloud、Mybatis、多线程并发、netty、MySQL、MongoDB、Elasticsearch、Redis、HBASE、RabbitMQ、RocketMQ、Pulsar、Kafka、Zookeeper、Linux、设计模式、智力题、项目架构、分布式相关、算法、面试题
:star2:TODO list:star2:
内容概览↓↓
Java↓↓ | 基础部分 | JVM | 多线程 | ||
---|---|---|---|---|---|
计算机网络↓↓ | 网络协议分层 | TCP | UDP | 三次握手 | 四次挥手 |
TCP怎么保障可靠传输 | HTTPS | HTTP面试题 | |||
数据库↓↓ | MySQL | MongoDB | HBASE | NebulaGraph | Elasticsearch |
Redis | SQL问题 | ||||
消息队列↓↓ | Redis | RabbitMQ | RocketMQ | Kafka | Zookeeper |
Pulsar | |||||
框架↓↓ | Spring | SpringMVC | SpringBoot | SpringCloud | SpringCloudAlibaba |
Mybatis | Netty | ||||
Linux↓↓ | 进程-线程-文件描述符 | IO模型 | select-poll-epoll | ||
分布式相关↓↓ | 分布式锁 | 分布式事务 | 分布式唯一ID设计 | CAP理论 | 一致性算法 |
架构↓↓ | 系统设计 | 计算和储存分离 | DDD领域驱动设计 | ||
容器技术↓↓ | Docker | Kubernetes | |||
数据结构和算法↓↓ | 排序算法 | 树相关 | BFS | DFS | 回溯算法 |
二分法 | 贪心算法 | 动态规划 | 分治思想 | ||
设计模式↓↓ | |||||
大数据↓↓ | Hadoop | ||||
面试↓↓ | 职业规划和学习习惯 | 场景设计 | 智力题 | 面试解答 | 商城类问题 |
内容详情
Java-基础部分↑↑
- 基本类型
- 包装类型
- 关键字
- Object
- String
- 数组
- 继承
- 反射
- 异常
- 泛型
- 容器
-
List
- Vector
- LinkedList
- ArrayList
- CopyOnWriteArrayList
-
Set
- HashSet
- LinkedHashSet
- TreeSet
- queue
-
Map
- HashMap
- LinkedHashMap
- TreeMap
- ConcurrentHashMap
- IdentityHashMap
- WeakHashMap
-
List
-
Java-IO
- 文件io
- 网络io
- NIO
- Java长期支持版本新特性
- Java虚拟线程
Java-JVM↑↑
-
内存结构
- 程序计数器
- Java虚拟机栈
- 本地方法栈
- 堆
- 方法区
- 运行时常量池
- 直接内存
-
垃圾回收
-
判断一个对象能否被回收
- 引用计数法
- 可达性算法
- 哪些可以作为是根节点
- 方法区的回收
- finalize()
-
引用类型
- 强引用
- 软引用
- 弱引用
- 虚引用
- 分代收集理论
- Java对象头
-
GC定义
- 新生代收集(Minor GC/Young GC)
- 老年代收集(Major GC/Old GC)
- 混合收集(Mixed GC)
- 整堆收集(Full GC)
-
回收算法
- 标记-清除
- 标记-复制
- 标记-整理
-
Hotspot算法实现细节
- 根节点枚举GC Roots
- 安全点Safe Point
- 安全区域Safe Region
- 记忆集Remembered Set与卡表Card Table
- 写屏障Write Barrier
-
并发的可达性分析
- 为什么需要并发标记
-
三色标记Tri-color Marking
- 什么是三色标记
-
垃圾回收器
- Serial收集器
- ParNew收集器
- ParallelScavenge收集器
- SerialOld收集器
- ParallelOld收集器
- CMS收集器
- G1收集器
- ZGC收集器
-
判断一个对象能否被回收
-
内存分配与回收策略
- 对象优先在 Eden 分配
- 大对象直接进入老年代
- 长期存活的对象进入老年代
- 动态对象年龄判定
- 空间分配担保
-
类加载机制
-
有哪些类加载器
- 1.引导类加载器 bootstrap classloader
- 2.扩展类加载器 extensions classloader
- 3.应用程序类加载器 application classloader
- 4.自定义类加载器 java.lang.classloder
-
生命周期
- 1. 加载
- 2. 验证
- 3. 准备
- 4. 解析
- 5. 初始化
- 双亲委派模型
-
有哪些类加载器
-
JVM调优
- 原则
- jvm调优
- JVM调优目标
- JVM调优的步骤
- JVM参数解析及调优
-
Java即时编译
- 什么是
- Java的执行过程
- 1.JVM中的编译器
- 2.分层编译
- 3.即时编译的触发
-
编译优化
- 1. 中间表达形式(Intermediate Representation)
- 2.方法内联
- 3. 逃逸分析
- 4. Loop Transformations
- 5. 窥孔优化与寄存器分配
Java-多线程↑↑
-
线程
-
线程的生命状态
- 新建new
- 可运行runnable
- 阻塞blocked
- 等待waiting
- 期限等待timed waiting
- 死亡terminated
-
使用线程
- 继承Thread
- 实现Runnable接口
- 实现Callable接口
- Callable如何返回值的
- FutureTask
-
线程基本方法
- wait
- sleep
- yield
- interrupt
- join
- notify
- await() signal() signalAll()
- Java里怎么保证多个线程的互斥性
- 线程和进程的区别
-
怎么让多个线程有序执行
- join方法
- 线程池
- lock-condition
-
Java线程和操作系统的线程区别
- Java线程在操作系统上本质
- 操作系统中的进程(线程)状态
- 操作系统中线程和Java线程状态的关系
-
线程的生命状态
-
volatile
-
机器内存模型
- 多核下的缓存一致性问题
- 指令重排
- JMM
-
作用
- 可见性
- 禁止指令重排
- volatile解决可见性的代码
- 验证volatile不具备原子性
-
机器内存模型
-
Java对象头
-
锁机制
- Synchronized
-
Lock
- ReentrantLock
-
锁优化
- 自旋锁
- 循环
- 锁消除
- 锁粗化
- 锁升级
- 死锁
- synchronized锁和lock锁的区别
-
线程池
-
创建线程池的方式
-
1、Executors
- newCachedThreadPool
- newFixedThreadPool
- newScheduledThreadPool
- newSingleThreadExecutor
- 2、ThreadPoolExecutor
-
1、Executors
-
ThreadPoolExecutor
- 参数含义
- ThreadPoolExecutor原理流程
- 如何释放线程
- 如何设置线程数
-
创建线程池的方式
-
CAS
- 原理
- 参数
- CAS的问题
-
AQS
-
AQS(AbstractQueuedSynchronizer)
- 工作原理概要
- 同步队列模型
-
ReentrantLock
- Sync (extends AbstractQueuedSynchronizer)
-
NonfairSync (extends Sync) 非公平锁
- lock
- unlock
- FairSync (extends Sync) 公平锁
- Condition
-
同步工具类
- CountDownLatch
- CyclicBarrier
- Semaphore
-
AQS(AbstractQueuedSynchronizer)
-
ThreadLocal
- 原理
- ThreadLocalMap
-
源码分析
- get
- set
-
使用场景
- 每个线程维护了一个“序列号”
- Session的管理
- SimpleDateFormat
- 手动释放ThreadLocal遗留存储?你怎么去设计/实现?
- 弱引用导致内存泄漏,那为什么key不设置为强引用
- 线程执行结束后会不会自动清空Entry的value
- threadlocal如果不remove,出问题了怎么补救?
- FastThreadLocal
计算机网络↑↑
-
网络协议分层
- OSI 7层(基本只是拿来作比较)
-
TCP/IP 5(4)层
-
应用层
-
常见的协议
- 域名系统
- 文件传送协议
- SMTP电子邮件协议
- 远程登录协议
-
常见的协议
-
传输层
-
常见的协议
- TCP
- UDP
-
常见的协议
- 网络层
-
数据链路层
- 封装成帧
- 透明传输
- 差错检测
- 物理层
-
应用层
-
TCP报文
-
UDP报文
- IP报文
-
TCP/IP
-
UDP 和 TCP 的特点
- UDP
- TCP
-
三次握手
-
四次挥手
-
TCP怎么保障可靠传输
- 数据合理分片和排序
- 数据校验:校验和
- TCP 的接收端会丢弃重复的数据
- 超时重传
- 流量控制
- 拥塞控制
- ARQ协议
-
如何实现可靠UDP传输
-
HTTP长连接还是短连接?
-
-
HTTP
- 特点
-
方法
- get
- head
- post
- put
- patch
- delete
- options
- connect
- trace
-
状态码
- 1XX
- 2XX
- 3XX
- 4XX
- 5XX
-
HTTPS
- 什么是HTTPS
- 端口
- HTTPS解决的问题
- HTTPS加密过程
- HTTPS的CA证书放了什么,公钥放在CA里吗?
- CA证书是在客户端还是服务器
- HTTP1.1和HTTP1.0的主要区别
- HTTP2.0和HTTP1.x的区别
- HTTP的request和response格式
- cookie
- session
-
JWT
- json web token
- 格式
- 特点
-
跨域
- 什么是跨域?
- 同源策略
-
解决方案
- JSONP
- CORS
-
网络攻击行为
- CSRF攻击
- XSS
- SQL注入
- DDOS
- SYN Flood攻击
-
CDN
- 什么是CDN
- 好处
-
HTTP面试题
- 在浏览器中输入url地址显示主页的过程
- QPS和TPS的区别
- 有哪些编码格式(GBK,UTF-8,ISO-)有没有想过为什么会有这么多的编码格式
- 实现一个长URL转短URL
数据库↑↑
MySQL↑↑
-
MySQL
- 架构
-
储存引擎
- InnoDB
- MyISAM
- 索引
-
事务
-
ACID
- 原子性(Atomicity,或称不可分割性)
- 一致性(Consistency)
-
隔离性(Isolation)
-
隔离级别
- 读未提交:read uncommitted
- 读已提交:read committed
- 可重复读:repeatable read
- 串行化:serializable
-
隔离级别
- 持久性(Durability)
-
ACID
-
事务日志
- redo log(重做日志)
- undo log(回滚日志)
- 二进制日志( binlog )
-
锁
- 行级锁
- 表级锁
- 页锁
-
切分
- 水平切分
- 垂直切分
-
复制
- 主从复制
-
中间件
- mycat
- ShardingSphere
- SQL优化
- MySQL与PostGreSQL的区别
SQL问题
- count(*)分页
MongoDB↑↑
- MongoDB
- 特点
-
关键组件
- _id
- 集合
- 游标
- 数据库
- 文档
- 字段
- 单机mongo架构
- 集群模式1-MongoDB 复制(副本集)Replica set(主从关系)
- 集群模式2-MongoDB 分片
- WiredTiger存储引擎
HBASE↑↑
-
HBASE
- 什么是?
- 列式存储
-
架构
- 架构图
-
HBase 架构组件
- Regions
- HBase Master
- Zookeeper
- HBase Meta Table
- Region Server 组成
- HBase 写数据步骤
- HBase MemStore
- HBase Region Flush
- HBase HFile
- HBase Read 合并
- HBase Minor Compaction
- HBase Major Compaction
- Region = Contiguous Keys
- Region 分裂
- Region 负载均衡
- HDFS 数据备份
- HBase 故障恢复
-
Apache HBase 架构的优缺点
- 优点
- 缺点
Elasticsearch↑↑
-
Elasticsearch
- es的特点
- 应用场景
-
Elasticsearch基本概念
- 索引(index)
- 类型(type)
- 文档(document)
- 映射(mapping)
- 倒排索引
-
集群
-
基本概念
- 节点(Node)
- 集群(Cluster)
- 分片索引(Shard)
- 索引副本(Replica)
- 集群简单原理
- 插入数据流程
- 查询数据流程
-
基本概念
- 选举算法
-
es性能优化
- 加大filesystem cache大小
- 数据预热
- 冷热分离
- document设计
- 禁止直接分页
- es的分词器有哪些
- es为什么这么快
- es 的分页方案
- es 的查询流程
Nebula Graph↑↑
-
什么是Nebula Graph
- 什么是图数据库
- Nebula Graph 的优势
-
数据模型
-
数据模型
- 图空间(Space)
- 点(Vertex)
- 边(Edge)
- 标签(Tag)
- 边类型(Edge type)
- 属性(Properties)
- 有向属性图
-
数据模型
-
路径
- walk
- trail
- path
- 点 VID
-
服务架构
- 架构总览
- Meta 服务
- Graph服务
- Storage服务
消息队列↑↑
Redis↑↑
- Redis
RabbitMQ↑↑
-
RabbitMQ
- 概念介绍
- 架构图
-
exchange类型
- Direct
- Fanout
- Topic
- RabbitMQ 消息持久化
- 集群
- 交换器无法根据自身类型和路由键找到符合条件队列时,会如何处理?
- RabbitMQ 的六种模式
- 死信队列应用场景
- 事务机制
-
Confirm模式
- producer端confirm模式的实现原理
- 开启confirm模式的方法
- 编程模式
RocketMQ↑↑
-
RocketMQ
- 架构图
-
组件
- NameServer
- Broker
- Producer
- Consumer
- 消息特性
- 消息功能
- rocket的事务实现机制
-
Broker 集群部署架构
- 多 Master 模式
- 多 Master 多 Salve - 异步复制 模式
- 多 Master 多 Salve - 同步双写 模式
- Dledger 模式
Kafka↑↑
-
Kafka
- 架构图
-
概念
- topic
- partition
- segment
- offset
- broker
- producer
- consumer
- Kafka零拷贝
-
常见问题
- kafka中zookeeper的作用
- kafka的consumer是拉模式还是推模式
- kafka生产者丢消息情况
- kafka消费者丢消息情况
- Kafka如何保证高可用性
- Kafka的消息保存在哪里?Kafka的消息是如何分区的?
- Kafka是如何处理流量峰值的?
- Kafka消息压缩方式
- Kafka的重平衡机制是什么?
- Kafka中的生产者和消费者是什么?Kafka是如何确保数据的顺序性和一致性的?
- kafka消费组怎么消费一个topic的数据
- Kafka有哪些优缺点?
- Kafka的API是什么?如何使用Kafka API实现生产和消费?
- 如何部署和扩展Kafka集群?
Zookeeper↑↑
-
Zookeeper
- 概念
- 用zookeeper可以干嘛
-
数据结构
- ZNode
- 监听机制
-
角色
- leader
- follower
- Observer
- Zookeeper Leader 选举原理
-
常见的问题
- 什么是Zookeeper?它的作用是什么?
- Zookeeper是如何实现数据的一致性和可靠性的?
- Zookeeper中的watcher是什么?如何使用watcher机制实现分布式锁?
- Zookeeper的性能瓶颈在哪里?如何优化Zookeeper的性能?
- 如何在Zookeeper集群中进行数据的备份和恢复?
Pulsar↑↑
-
Pulsar
- pulsar的优势
-
Apache Pulsar 架构
- Topic 与分区
- 物理分区与逻辑分区
-
消息存储原理与 ID 规则
- 消息 ID 生成规则
- 分片机制详解:Legder 和 Entry
-
消息副本与存储机制
- 消息元数据组成
- 消息副本机制
- 消息恢复机制
-
pulsar的消息模式
- 独占模式(Exclusive)
- 灾备模式(Failover)
- 共享模式(Shared)
-
定时和延时消息
- 相关概念
- 适用场景
- 使用方式
- 定时消息
- 延时消息
- 使用说明和限制
-
消息重试与死信机制
- 自动重试
- 自定义参数设置
- 重试规则
- 重试消息的消息属性
- 重试消息的消息 ID 流转
- 主动重试
-
常见面试题
- 什么是消息队列
- 为什么要使用消息队列
- 如何保证消息队列高可用
- 如何保证消息队列不被重复消费(幂等性)
-
如何保证消息的可靠传输
- 生产者丢数据
- MQ丢数据
- 消费者丢数据
- 如何保证消息的顺序性
- 如何处理消息堆积
- mq 中的消息过期失效了
Redis↑↑
- 特点
- Redis为什么这么快
- 常见使用场景
-
数据类型
- redisObject
- string
- list
- hash
- set
- zset(sorted set)
- bitmap
- HyperLogLog
- 内存回收策略
-
持久化方式
- RDB快照
- AOF追加
- Redis 中的事务
-
常问故障场景
- 缓存雪崩
- 缓存穿透
-
集群
- 主从复制模式
- Sentinel(哨兵)模式
- Cluster 集群模式
-
Redis Cluster 节点通信原理:Gossip 算法
- Gossip 简介
- 节点状态和消息类型
- Redis cluster伸缩的原理
- redis索引
Redis常见面试题↑↑
- 储存结构和使用场景
- 淘汰策略
Spring↑↑
-
Spring
- 架构图
- 模块
-
IOC
- IOC和DI的概念
- 使用IOC的好处
- Spring IoC的初始化过程
- Spring bean的生命周期
- bean的作用域
- 循环依赖问题
-
AOP
- AOP原理
- AOP术语
- Spring对AOP的支持
-
怎么定义一个注解
- 引入依赖
- 定义注解
-
事务
- Spring 支持两种方式的事务管理
- 事务的传播性 Propagation
- spring事务失效的场景
-
spring使用的设计模式
- 简单工厂
- 工厂方法
- 单例模式
- 适配器模式
- 装饰器模式
- 代理模式
- spring中properties和yml的加载顺序
- 使用@Autowired注解自动装配的过程是怎样的?
- @Autowired和@Resource之间的区别
- Spring中BeanFactory与FactoryBean的区别
SpringMVC↑↑
-
SpringMVC
- 流程
- 执行流程
SpringBoot↑↑
-
SpringBoot
- springboot启动流程
- 怎么让Spring把Body变成一个对象
- SpringBoot的starter实现原理是什么?
Springcloud↑↑
-
服务注册与发现
- eureka
- consul
- ribbon
- loadbalancer
- feign
- openFeign
- hystrix
- resilience4j
- zuul
- zuul2
- getway
- springcloud config
- Nacos
SpringcloudAlibaba↑↑
-
SpringcloudAlibaba
- Nacos
- Sentienl
Linux↑↑
- 文件和目录的操作
- 查看文件
- 管理用户
- 进程管理
- 打包和压缩文件
- grep+正则表达式
- Vi编辑器
- 权限管理
- 网络管理
- cpu100%怎么排查
- 用户空间与内核空间
-
Linux的进程、线程、文件描述符是什么
- 进程切换
- 进程的阻塞
- 文件描述符fd
- 缓存 I/O
-
IO模型
-
select、poll、epoll
- 进程间8种通信方式详解
- Linux物理内存和虚拟内存
- 页面置换算法
- 进程调度算法
Mybatis↑↑
- 什么是mybatis
- JDBC执行六步骤
- mybatis执行8步骤
- MyBatis整体架构
- mybatis缓存
Netty↑↑
-
重要的组件
- Channel
- ChannelFuture
- EventLoop
- ChannelHandler
- ChannelPipeline
- TaskQueue
-
netty的使用示例
- 服务端
- 客户端
-
TCP粘包/拆包问题
- 什么是粘包拆包
- 发生的原因
- 粘包解决策略
- netty粘包问题解决方案
-
解编码技术
- Java序列化的缺点
- Google的protobuf
- Facebook的Thrift
- JBoss的Marshalling
- MessagePack
-
高性能的原因
- 非阻塞io
- 零拷贝
- 内存池
-
高效的Reactor线程模型
- Reactor 单线程模型
- Reactor 多线程模型
- (采用)主从 Reactor 多线程模型
- 无锁化串行设计
- 高性能的序列化框架
- 灵活的TCP 参数配置能力
- netty相关问题
分布式相关↑↑
-
分布式锁
- 基于数据库
- Redis
- zookeeper
-
分布式事务
- 两阶段提交
- TCC(Try-Confirm-Cancel)
- 本地消息表
- 可靠消息最终一致性
- 尽最大努力通知
- Apache Seata
-
分布式唯一ID设计
- UUID
- 多台MySQL服务器
- Twitter Snowflake
- 百度UidGenerator算法
- 美团Leaf算法
-
CAP理论
- 一致性 Consistency
- 可用性 Availability
- 分区容错性 Partition Tolerance
- 常见的注册中心
-
BASE
- 基本可以 Basically Available
- 软状态 Soft-state
- 最终一致性 Eventually Consistent
-
一致性算法
- Paxos
- Raft
容器技术↑↑
-
Docker
- Docker简介
- Docker常用命令
- Docker应用架构
- 底层实现原理
-
Kubernetes
数据结构和算法↑↑
-
排序算法
-
树相关 --todo
-
BFS --todo
-
DFS --todo
-
回溯算法 --todo
-
二分法 --todo
-
贪心算法 --todo
-
动态规划 --todo
-
分治思想 --todo
- LRU
- LFU
- 加减乘除
设计模式↑↑
- 工厂模式
- 单例模式
- 建造者模式
- 原型模式
- 适配器模式
- 装饰器模式
- 代理模式
- 外观模式
- 桥接模式
- 组合模式
- 享元模式
- 策略模式
- 模板方法模式
- 观察者模式
- 迭代子模式
- 责任链模式
- 备忘录模式
- 状态模式
- 访问者模式
- 中介者模式
- 解释器模式
职业规划和学习习惯↑↑
- 项目中遇到的问题
- 职业规划
- 平时规则
场景设计↑↑
- 有A、B两个大文件,每个文件几十G,而内存只有4G,其中A文件存放学号+姓名,而B文件存放学号+分数,要求生成文件C,存放姓名和分数。怎么实现?
- 秒杀系统怎么设计
- 唯一ID设计
- 产品上线出问题怎么定位错误
- 大量并发查询用户商品信息,MySQL压力大查询慢,保证速度怎么优化方案
- 海量日志数据,提取出某日访问百度次数最多的那个IP。给定a、b两个文件,各存放50亿个url,每个url各 占64字节,内存限制是4G,让你找出a、b文件共同的url?
- 一般内存不足而需要分析的数据又很大的问题都可以使用分治的思想,将数据hash(x)%1000分为小文件再分别加载小文件到内存中处理即可
- 如何保证接口的幂等性
- 缓存和数据库不一致问题
- 什么是SPI
- 什么是RPC?
- gRPC
- 一个优秀的RPC框架需要考虑的问题
- 什么是DDD
- Java实现生产者消费者
- Java实现BlockQueue
- 解决哈希冲突的方法
- 排行榜设计
智力题↑↑
- 100只试管里有-只是有毒的,现在有10个小白鼠,如何最快速地判断出那只试管有毒
- 共1000瓶药水,其中I瓶有毒药。已知小白鼠喝毒药一天内死若想在一天内找到毒药,最少需要几只小白鼠?
- 只有两个无刻度的水桶,-个可以装6L水,-一个可以装5L水,如何在桶里装入3L的水
- 25匹马,5个赛道, 每次只能同时有5匹马跑,最少比赛几次选出前三名?家里有两个孩子,一个是女孩,另一个也是女孩的概率是多少?
- 烧一根不均匀的绳,从头烧到尾总共需要1个小时。现在有若干条材质相同的绳子,问如何用烧绳的方法来计时一个小时十五分钟呢?
- 共12个一样的小球,其中只有一个重量与其它不一一样(未知轻重),给你一个天平,找出那个不同重量的球?
- 有10瓶药,每瓶有10粒药,其中有一瓶是变质的。好药每颗重1克,变质的药每颗比好药重0.1克。问怎样用天秤称一次找出变质的那瓶药?
- 你有两个罐子,50个红色弹球,50个蓝色弹球,如何将这100个球放入到两个罐子,随机选出一个罐子取出的球为红球的概率最大?
- 抢30是双人游戏,游戏规则是:第一个人喊"1"或"2",第二个人要接着往下喊一个或两个数,然后再轮到第一个人。 两人轮流进行下去。最后喊30的人获胜。问喊数字的最佳策略。
- 某人进行10次打靶,每次打靶可能的得分为0到10分,10次打靶共得90分的可能性有多少种
架构↑↑
-
系统设计
-
计算和储存分离
-
DDD领域驱动设计
大数据↑↑
-
Hadoop
-
hadoop面试问题
-
面试解答↑↑
- HR会问什么
- 面试解答6月牛客
- 面试解答7月牛客
- 面试解答9月牛客
- 面试解答10月牛客
商城类问题↑↑
- 秒杀
- 超卖
- 订单延迟
免责声明↑↑
某些知识点、观点、图片是从各种优秀博主、作者、大佬们的文章里或文献里提取的,我只是搬运工,如果觉得有侵犯到您的权益,请联系我,我将根据您的要求修改(添加您的出处链接、删除、修改....),谢谢大佬!
最后↑↑
不积跬步无以至千里