【八股文】从基础到微服务

文章目录


###

八大基本类型

占用:1248 48 21
取值范围:占用空间x8-1次方,char是0-65535

开发过程中用到的集合

LinkedHashMap——LRU算法——缓存
HashMap,List——利用key不可重复和键值对特性,对多级目录进行分级封装
ConcurrentHashMap——线程安全
ArrayList——实体类封装的时候

多态的优点

1.忽略某个对象的类型,就可以调用某些方法——简化性
2.提高了程序的可拓展性和可维护性——可替换性
3.统一调用标准,多态又可以叫做动态绑定,实现类型的解耦。——接口性

内层控制外层循环
		a:for (int i = 0; i < 5; i++) {
            b:for (int j = 0; j < 5; j++) {
              break a;
            }
        }
equals和hashcode
@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        RewriteEqHashCode that = (RewriteEqHashCode) o;
        return Objects.equals(id, that.id) &&
                Objects.equals(name, that.name);
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(id, name);

成员变量,局部变量

代码位置不同,生命周期不同,初始化不同,内存不同。

ArrayList底层存取值怎么实现的,是不是线程安全的,扩容是怎么实现的

扩容:
1.5倍扩容,CopyOf()。
如果扩容一半不够,就将目标size作为扩容后的容量。
采用的是浅拷贝:只拷贝引用。

存值:
首先判断容量够不够,然后通过size自增作为下标,通过数组的方式放进去。如果不够,会层层调用grow方法进行扩容。如果调用的是addall方法,则会把添加的集合转为数组并拿到length,进行容量判断,如果不够,则扩容。并且对比扩容的size和新的size比较,以大的为准。
如果指定下标add,会判断下标是否合法,然后判断容量,并通过arraycopy方法,将后半段元素后移1。
取值:
如果输入下标取值,则会检查下标是否合法,如果OK,则通过数组的方式取值。并通过arrycopy进行迁移元素,并把最后一个空位设为null。
如果传入一个value,则会判断非空后进行遍历,并取出。

HashMap的底层原理,ConcurrentHashMap的实现原理,存取值的时候是怎么实现的。

1、map.put(k,v)实现原理
(1)首先将k,v封装到Node对象当中(节点)。
(2)然后它的底层会调用K的hashCode()方法得出hash值。
(3)通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。

2、map.get(k)实现原理
(1)先调用k的hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。
(2)通过上一步哈希算法转换成数组的下标之后,在通过数组下标快速定位到某个位置上。如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着K和单向链表上的每一个节点的K进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的K和参数K进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value。

进程

正在运行的程序,占用内存区域,CPU进行运行和计算。
特点:
独立性——没有允许的情况下不可以相互访问
动态性
并发性——不会相互影响

重载和重写的区别
Java创建对象的方式

使用构造方法:new,反射
不使用构造方法:反序列化 (深拷贝),clone(浅拷贝–深拷贝序列化,深拷贝变量也clone)

Object的默认方法

1个本地注册方法
1个getClass()
4个,hash,toString,Equals,clone
2个notify
3个wait
1个finalize()

包装类的Cache

在这里插入图片描述

多态中静态方法的执行

静态方法不同于静态代码块,是由开发者调用。
只能通过类名点处理。子类可以继承父类的静态方法。
如果同名,不算重写,子类只能调用到子类的方法。

反转字符串程序

0.reverse
1.倒序拼接
2.切割递归
3.二分递归

Java异常处理机制

请添加图片描述

常用的IO类
代码规范的理解

命名规范,
注释规范,
代码结构化,模块化
开发文档的习惯

项目中用到final的地方

静态常量
参数:基本类型为常量,引用类型不能被重新赋值

深拷贝和浅拷贝的区别

浅拷贝:只拷贝一层。
深拷贝:新开辟堆内存中的数据。

对集合有二次加工的处理吗

有,在自己写的本地缓存中。重写了LinkedHashMap的removeEldestEntry()方法,把删除的元素返回给成员变量,让基础Map能删除已经不存在的key。

@ToString
public class LRUBirdCacheImpl implements BirdCache {
    private BirdCache birdCache;
    private Map<Object,Object> linkedHashMap;
    private int maxKey;
    private Object eldestKey;
    public LRUBirdCacheImpl(BirdCache birdCache, int maxKey) {
        this.birdCache = birdCache;
        this.maxKey = maxKey;
        this.linkedHashMap =
                new LinkedHashMap<Object, Object>( maxKey,0.75F,true){
                    //此方法每次执行keyMap的put操作时调用
                    @Override
                    protected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {
                        boolean flag=size()>maxKey;
                        if(flag)eldestKey=eldest.getKey();
                        return false;
                    }
                };
    }
    
    @Override
    public void saveBird(Object key, Object value) {
        Object put = linkedHashMap.put(key, key);
        if(eldestKey!=null){
            birdCache.removeBird(eldestKey);
        }
        birdCache.saveBird(key,value);
    
    }
    
    @Override
    public Object getBird(Object key) {
        linkedHashMap.get(key);
        Object o = linkedHashMap.get(key);
        return o;
    }
    
    @Override
    public Object removeBird(Object key) {
        return birdCache.removeBird(key);
    }
    
    @Override
    public void clear() {
        birdCache.clear();
        linkedHashMap.clear();
    }
    
    @Override
    public int size() {
        return birdCache.size();
    }
}
线程池的创建

自定义创建:

ThreadPoolExecutor
ScheduledThreadPoolExecutor
ForkJoinPool

Executors工具类创建:

Fixed:定长的线程池
Scheduled:
Single:单线程的
Cache:0-Integer.MAX

多线程的使用场景

定时类:
定期采集信息,定期备份日志

异步类:
记录日志

耗时类:
耗时类任务

Tomcat的请求层面

双亲委派

请添加图片描述

类加载器(Classloader):
类加载阶段中的“通过一个类的全限定名来获取此类的二进制字节流”这个动作放到 Java 虚拟机外部去实现。
作用:加载class文件进入JVM,审查类由谁加载(双亲委派机制),将class重新解析成JVM要求的对象格式
一阶段:加载阶段——字节码加载到内存
1:通过全限定名来获取类的字节流
2:将字节流转为方法区的运行时数据
3:在堆中生成一个Class对象,作为访问入口
二阶段:验证阶段——确保Class文件的字节流中包含的信息符合当前虚拟机的要求
1:格式验证:Class文件格式规范
2:元数据验证:是否符合JAVA语法
3:字节码验证:数据流和控制流分析,确保不危害虚拟机
4:符号引用验证:符合引用转直接引用
三阶段:
1:类资源的内存分配
2:解析引用
3:初始化,执行静态代码

一言概之,双亲委派模型,其实就是一种类加载器的层次关系。
BootStrap——完全由JVM控制,加载JVM需要的类
Extension——服务目标在ext目录下的,依赖等
Application

破坏双亲委派三大情况:
jdk1.2之前
缺陷导致,——通过线程上下文类加载器解决,例如SPI的JDBC
热部署

加载Class的两种方式:
隐式:JVM在解析引用的时候发现内存没有,会申请加载。
显式:
this.getClass().getClassLoader().loadClass()
Class.forName()

流程:
收到加载类的请求。
从底向上检查类是否已加载。
如果没有加载,自顶向下尝试加载该类。

优点:
1,防止底层类被篡改。
2,避免重复加载类信息。

JVM结构,运行顺序

JVM的基本组成:

  • JVM指令集
  • 类加载器
  • 执行引擎:jvm的核心,解析JVM字节码指令,每个java线程就是一个执行引擎的实例。
  • 运行时数据区:将内存分为若干个区
  • 本地方法区:调用C方法返回的结果
    请添加图片描述

线程私有的:

  • 程序计数器:线程私有的,行号指示器。
  • 虚拟机栈:栈帧,执行完方法清楚栈帧。调用其他方法推到栈顶(活动栈帧)。
  • 本地方法栈

公共的:

  • 堆():堆区放对象,堆栈放引用。
  • 方法区(永久区):常量池,域,方法数据,方法体,构造函数,类中的专有方法,实例初始化,接口初始化。【运行时常量池】
类加载知识点
HashMap的遍历方式

1:转EntrySet用迭代器
2:转KeySet用迭代器
3:foreach
4:map.forEach()——lamdba
5:map.entrySet().Stream().forEach
6:map.entrySet().parallelStream().forEach

最高效:parallelStream

HashSet怎么保证元素唯一
lock锁
锁升级
sync的实现原理
sync和volatile

volatile:
对象存放在堆内存,如果是多个线程操作,是共享资源。
对于多实例来说,只有静态资源才是共享资源。

每一个线程还存在自己的工作内存,线程的工作内存,保留了被线程使用的变量的工作副本。

线程对变量的所有的操作(读,取)都必须在工作内存中完成,而不能直接读写主内存中的变量。

解决可见性问题:
加锁:进锁会清空工作内存,从主内存拷贝最新的数据到工作内存成为副本。
volatile:volatile保证不同线程对共享变量操作的可见性——主内存的值改变,工作内存的副本会失效,需要重新读。通过嗅探,遵循MESI缓存一致性协议。

总线风暴:不断的从主内存嗅探和cas不断循环,无效交互会导致总线带宽达到峰值。(少使用)

重排序(as-if-serial):编译器优化——>指令集并行——>内存系统

内存屏障:重排序时,不能把屏障后面的重排序到屏障前面。

volatile和sync的区别:
1:volatile只能用在属性上。
2:只赋值的情况下,因为赋值是原子性,又保证了可见性,从而保证线程安全。

怎么理解资源独立分配

ThreadLocal:
每个Thread内部都有一个Map(ThreadLocalMap),是Thread的一个属性。
key是当前ThreadLocal对象——弱引用,value却是强引用。

内存泄漏问题:
造成内存泄露——解决:手动remove,静态私有。

线程复用问题:前后remove

使用场景:
1:存储用户Session
2:数据库连接,处理数据库事务
3:数据跨层传递
4:spring解决线程安全问题

有状态:有属性——比如pojo
无状态:无属性——controller

线程的状态的转换关系,主动阻塞和被动阻塞

等待阻塞,同步阻塞,其他阻塞。

join():并行变串行
interrupt():更改标识,抛异常,中断阻塞请添加图片描述

BIN和NIO的区别,怎么实现多路复用

BIN:Block-IO

网络IO是可能阻塞的,为了不阻塞整个进程,采用多线程。

NIO:Non-Blocking-IO

NIO 流——非阻塞IO:
1:IO流——面向流,NIO流——面向缓冲——在NIO厍中,所有数据都是用缓冲区处理的。
2:NIO流通过通道进行读写,双向的。
3:NIO有选择器,一个线程可以处理多个通道。

多路复用:
可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
Linux中的 select,poll,epoll 都是IO多路复用的机制。

程序注册一组socket文件描述符给操作系统。

过程:
1:创建epoll,内核层创建了一个数据表。
1):避免了无所谓的数据复制,ctl可以来管理增删改。
2):fork子进程可以继承这个表,方便并行监听。
2:使用epoll_ct1接口注册要监听的事件,比如socket。
3:使用epoll_wait来等待事件的发生——阻塞的。
无限循环:注册,等待,注册,等待…
epoll有水平触发(默认)和边缘触发。

HTTPS怎么实现的网络安全性

http缺点:
明文不加密——可能被窃听
不验证身份——遭遇伪装
无法验证报文完整性——可能篡改

HTTPS = HTTP + 加密 + 认证 + 完整性保护

1:http采用了SSL+TLS协议。先通讯SSL,SSL再通讯TCP。
2:加密方式——对称加密,非对称加密,混合加密。
3:完整性——摘要算法。
4:证书认证——第三方CA

设计模式是用来干嘛的,为什么看设计模式

解决软件开发某些特定问题而提出的一些解决方案也可以理解成解决问题的一些思路。

通过设计模式可以帮助我们增强代码的可重用性、可扩充性、 可维护性、灵活性好。我们使用设计模式最终的目的是实现代码的高内聚和低耦合。

Map自定义一个实例作为Map的Key,需要满足什么条件。自定义类作为Key,有什么要求。

1:自定义实例不能是单例的,并且使用这个单例。
2:注意判断对象重复的规则是什么。

List用什么方式遍历

1:collection迭代器
2:list迭代器
3:foreach或for
4:点foreach+lamdba
5:转成流,点foreach
6:转成并发流,点foreach

Remove删除元素做过什么其他操作

1:检查下标是否合法。
2:检查modCount。
3:根据下标+偏移量删除。
4:size-1
5:返回。

进程和线程在地址空间上有什么区别
进程是分配资源的基本单位,怎么理解

PCB用来描述进程。
1:每个进程都有私有用户空间,其他进程不可见。
2:同时有进程共享的内核空间。

线程和资源有什么关系
gitee代码冲突怎么解决

1:拉取代码,发现冲突,解决再上传。
2:通过WebIDE在线手动解决

Gitee常用命令有哪些

add
push
pull
stash
stash pop

on和where

在left join中,无论on后面的是否为真。都会返回左表,inner join则不会。

mysql数据存在哪里

my.ini文件中进行配置:端口号,字符集,存放位置。

mysql函数
lower(username)
upper(username)
length(username)
substr(username,1,3) --含头含尾
caoncat(username,"123") --拼接123
replace(username,'1','100') --1换100
ifnull(sex,0) --nul换10
round(money,1) ceil(money) floor(money)
select now() -- 年与日 时分秒
select curdate() --年与日
select curtime() --时分秒
select now(),hour(now()),minute(now()),second(now()) from emp ;
select now(),year(now()),month(now()),day(now()) from emp ;

聚合函数

count(1) --快
count(username) --慢,只统计非null
min(id)
min(id)
sum(grade)
avg(grade) --平均数
工作中用到哪些数据库
事务是在哪里应用的
数据库中sql优化
索引的分类

功能区分:
主键索引(聚集索引),唯一索引,普通索引,全文索引
列数区别:
单值索引,联合索引
物理区分:
聚簇索引,非聚簇索引

索引的数据结构
事务的隔离级别
事务的传播方式
分页是怎么做的
#和$的区别,分别什么情况下使用
Mysql数据库悲观锁和乐观锁

乐观锁:
是自己实现的。通过version字段。

悲观锁:
读锁(共享锁):查询语句后面加lock in share mode,此时查询不提交,无法修改。
写锁(独占锁):增删改默认添加,for update

行锁:
通过索引项来实现。只有通过索引条件来索引时,才使用行锁,否则使用表锁。
两阶段协议:一个事务中,多个行锁的释放,是等到事务提交才进行释放。

间隙锁:
用范围条件进行检索,并请求锁时。对于区间内不存在的数据进行加锁。不互斥,但是防止插入这一个数据的操作。
1可以防止幻读。
1但是会放大锁的粒度,造成锁等待。因此避免使用范围条件。
2可能造成死锁

表锁:
行锁和事务是我们选择innodb的理由。但是某些情况下可以使用表锁,但很少:
1:更新大部分,或全部数据。
2:事务设计多个表,很复杂,可能引起死锁,造成大量事务回滚。

SQL:删除重复的记录
怎么创建索引
create [unique] index 索引名 on 表名(字段名)  --普通创建
Get和Post的区别

get用于查询,应该是非修改幂等的。
get会被浏览器主动缓存。且有长度限制。
get只有一个tcp数据包。

post用于改变数据
post的数据是放在请求数据的,所以是没有长度限制的
post会产生两个数据包,请求头先走,返回100.则再发送数据,返回200.
post不携带URL,只携带http版本。

Get传参的长度限制
HTTP状态码

1xx:请求正在处理
2xx:请求处理完毕
200:成功
201:已创建新资源
3xx:需要附加操作以完成请求,例如重定向
4xx:服务器无法处理请求
400:不理解
401:未授权
403:被拒绝
405:方法禁用,或不匹配
5xx:服务器处理请求出错
500:后端报错
503:服务不可用

POST上传有限制,上传文件过大怎么办。
union和union all的区别
mysql 中float和double的区别

4字节——8字节
32位——64位
小数点后6位——小数点后15位
取值范围不同

优缺点:
float速度快,科学运算反而慢。位数多了不精确,占用小,

联合索引中,最左的字段放在右边会命中吗?为什么?
mysql中的几个器

过滤器拦截器
前端传参时,是怎么和对象映射的

数据解析器,使用PropertyEditorSupport。

IOC和AOP
AOP是怎么调用的,静态代理和动态代理的区别

实现BPP接口,在初始化阶段进行调用方法链。
1.createAopProxy()选择代理类型
2.在invoke()方法中,获取拦截器,判断拦截器链是否为空。
3.获得proceed()方法。

Mybatis的优缺点

优点:ORM映射,减少代码量,可重用,半自动化灵活性高,sql和代码解耦相较于JDBC,动态sql。
缺点:依赖于数据库移植性较差,无法完全脱离sql

Mybatis的BIO接口支持重载吗
SpringMVC的请求原理
SpringMVC组件
SpringBoot读取配置文件的配置项,怎么读取。如果读取不到怎么办,除了@Value还有什么。

@Value
@ConfigurationProperties
@PropertySource

SpringBoot中的异常拦截怎么做的
SpringBoot依赖是怎么导入的
SpringBoot是怎么读取参数的
SpringBoot常用注解
SpringBoot的核心配置文件,什么格式,什么区别

bootstrap和application
yml或properties

优先级不同
bootstrap主要用于额外的资源来加载配置信息
属性不能被覆盖
解密属性

SpringBoot读取配置文件中的类,接口
Spring中的路由,怎么拼接路径前后的无意义参数
Bean生命周期
Bean的作用域
读取XML的几种方式

4种:DOM、DOM4J、JDOM、SAX

如何解决循环依赖

Spring的解决:使用三级缓存
3.单例对象工厂的缓存
2.提前曝光的单例对象缓存
1.单例对象的缓存

1.使用protoType作用域
2.通过Bean的加载顺序,先加载的使用setter注入,后加载的使用构造注入。

Spring的事务
介绍一下SpringBoot
单例有线程安全问题吗?原型呢?
HandlerMapping是什么时候工作的,程序启动的时候还是第一次请求的时候
Spring中的local有没有用过
Nginx有什么作用,怎么应用的
有没有参与过项目部署,怎么实现的
异常处理
SoringBoot是怎么运行的
Mybatis常用标签

定义sql语句:select insert delete update
映射对象:resultMap
动态sql:if foreach choose
格式化输出:where set trim
关联关系:collection assocition
引用:sql includ

Mybatis分页实现

通过插件接口,引入分页插件。

SpringMVC的注解
SpringBoot如何解决跨域问题

1:注解@CrossOrigin
2:继承WebMvcConfigurationAdapter,重写addCorsMappings
3:通过过滤器

Spring容器的启动问题
BeanFactroy怎么理解

BeanFactory:
是IOC容器的最基本形式,最基本的接口。并不是IOC的具体实现。具体实现比如:XmlBeanFactory,ApplicationContext等。

Factroy:
用户可以通过实现该接口定制实例化的Bean的逻辑。由Spring调用getObject()方法进行创建。

反向代理的过程
负载均衡怎么理解

流控模式有哪些?
项目中有没有用分布式架构
项目中有缓存吗,存在哪里的?
redis数据类型
redis中存储了哪些数据
redis常见命令
redis设置密码怎么登录
redis常用数据类型,有什么特点
redis的持久化机制
缓存崩坏三问,怎么解决
认证和权限是怎么实现的
MQ的用途

SpringCloud了解的多不多,尝试搭建微服务项目吗?
SpringCloud的组件
怎么实现分布式锁
Redis的分布式锁是怎么实现的
项目中涉及到高并发的问题了吗
Linux的权限
RPC什么原理,怎么调用远端服务像本地服务

其他

项目模块描述
项目使用了哪些技术
项目的日志
怎么用一个11L,7L的杯子,量出2L水
4L水,用1.5L的瓶子和2.5L的瓶子,怎么平均分
项目中遇到报错如何定位解决
理解老代码会遇见什么问题
更改代码影响别人的模块,怎么解决
项目里解决过什么有意义的东西
出现过哪些异常,什么原因造成的
测试时数据量小,发布后数据量大,怎么确保跑的起来
改老代码看不懂代码怎么解决
服务按领域拆分,按功能拆分,不同模块怎么办
改动影响了其他模块,导致出现问题,解决思路是怎么样的。
项目的表结构
介绍一下近期的项目,技术关键点,有挑战的地方。
项目中常用的数据结构,什么场景下使用
交互岗位沟通流程
简单工厂模式(静态工厂方法)

根据不同的条件创建不同的实例。
例子:Executors工具类
请添加图片描述

抽象工厂模式

请添加图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值