1.==与equals的区别?
-
"=="是一个操作符,用于比较两个对象的引用是否相等。它检查两个对象是否引用同一个内存地址。如果两个对象引用的是同一个内存地址,则返回true;否则返回false。
-
"equals()“是Object类中定义的方法(所有类都继承自Object类),用于比较两个对象的内容是否相等。它默认情况下与”=="相同,检查内存地址是否相等。但是,许多类(如String、Integer等)会重写equals()方法,使其比较对象的内容而不是内存地址。
2.arraylist linklist 底层什么数据类型?
-
ArrayList
:ArrayList
使用动态数组作为底层数据结构。具体来说,ArrayList
是一个 Object 数组,当创建ArrayList
对象时,实际上是创建了一个指定大小的 Object 数组。随着元素的添加,ArrayList
可以动态地增加数组的大小,以容纳更多的元素。在
ArrayList
中,元素的访问是通过索引来实现的,因为底层数组是连续的内存空间,通过索引可以直接访问到数组中的元素。 -
LinkedList
:LinkedList
使用双向链表作为底层数据结构。每个节点(Node)在链表中保存着一个元素,并且同时保存了指向前一个节点和后一个节点的引用。这使得在LinkedList
中插入和删除元素的操作更加高效,因为只需要修改节点的引用,而不需要像ArrayList
那样进行数组的拷贝和移动。在
LinkedList
中,元素的访问需要从链表的头部或尾部开始遍历,直到找到目标元素。因为链表不是连续的内存空间,不能像数组一样通过索引直接访问元素。
3.final
Java中关键字的作用是什么?如何以及在哪里可以使用它?
在Java中,final
是一个关键字,它用于表示不可改变的常量、不可继承的类或不可重写的方法。
4.Java中什么是线程?它与流程有何不同?
在Java中,线程(Thread)是程序的执行流程或执行路径。每个Java程序都至少有一个线程,即主线程(Main Thread)。线程是进程的一部分,一个进程可以包含多个线程,每个线程独立执行不同的任务。线程共享同一进程的内存空间和资源,这使得线程之间更加轻量级且可以高效地进行通信。
5.token存储在前端的哪里?
它在用户登录成功之后会返回给客户端,客户端主要以下几种存储方式:
1、存储在localStorage中,每次调用接口的时候都把它当成一个字段传给后台
2、存储在cookie中,让它自动发送,不过缺点就是不能跨域
3、拿到之后存储在localStorage中,每次调用接口的时候放在HTTP请求头的Authorization字段里面。token 在客户端一般存放于localStorage、cookie、或sessionStorage中。
6.数据库常用函数?
聚合函数:
COUNT:用于计算行数或非NULL值的数量。
SUM:用于计算数值列的总和。
AVG:用于计算数值列的平均值。
MIN:用于获取数值列的最小值。
MAX:用于获取数值列的最大值。
字符串函数:
CONCAT:用于连接两个或多个字符串。
LENGTH/LEN:用于获取字符串的长度。
UPPER/UCASE:用于将字符串转换为大写。
LOWER/LCASE:用于将字符串转换为小写。
SUBSTRING/SUBSTR:用于截取字符串的子串。
日期函数:
NOW/CURRENT_TIMESTAMP:用于获取当前日期和时间。
DATE:用于提取日期部分。
TIME:用于提取时间部分。
YEAR/MONTH/DAY/HOUR/MINUTE/SECOND:用于获取日期或时间的特定部分。
数学函数:
ABS:用于获取绝对值。
ROUND:用于四舍五入。
CEIL/CEILING:用于向上取整。
FLOOR:用于向下取整。
SQRT:用于计算平方根。
逻辑函数:
IF/ELSE:用于条件判断。
CASE:用于多条件判断。
AND/OR/NOT:用于逻辑运算。
7.集合中 Set List Map的区别?
List:是有序容器,输出的顺序就是插入的顺序,允许重复元素,可以通过索引访问元素。
Set:排列无序不可重复
Map:键值对映射,键无序且不允许重复,值允许重复,可以通过键获取对应的值。
8.arrayList和linkedlist 在增删改查操作上的别?谁速度快?谁的速度慢?
ArrayList在索引访问和修改操作上的性能较好,而LinkedList在任意位置的增加和删除操作上的性能较好。当需要频繁进行索引访问或修改操作时,ArrayList通常更快。当需要频繁进行任意位置的增加和删除操作时,LinkedList可能更快。
9.map key重复value是被替换还是抛弃 ?
如果使用put方法向Map中添加一个键值对,其中键已经存在于Map中,那么新的值将会覆盖原有的值。这样做是为了保持Map中键的唯一性,确保每个键只对应一个值。
10.String是基本数据类型吗?为什么不可变?
不是,因为它被final修饰它不能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变。
11.Java中如何创建线程?实现这一目标有哪些不同的方法?
通过实现Runnable
接口: 这是更常见和推荐的方式,因为Java支持单继承,如果已经继承了其他类,则无法再继承Thread
类。
通过继承Thread
类: 这种方式较为简单,但由于Java只支持单继承,可能限制了其他类的继承关系,因此不太推荐使用。
12.spring 单例还是多例 ?
默认是单利,如果想要多例,需要在类的名称上方用@Scope(“prototype”)。
13.spring 核心
IOC:控制反转,IOC控制反转,其思想是反转资源获取的方向,使用IOC就是为了防止在使用目标的过程中去直接new对象,而是采用调用方法的方式
DI: 依赖注入,ioc的一种表述方式,即组件以一些预先定好的方式,接收来自容器的注入
面向切面编程(AOP)
(核心)面相切面编程(AOP):将公共的,通用的,重复的代码单独开发,在需要的时候反织回去,底层的原理是动态代理
在面向对象编程(OOP)中,我们将事务纵向抽成一个个的对象,而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制,事务管理,日志记录等公用操作处理的过程,就是面向切面编程的思想。
14.mybatis 动态标签
<if>
标签:用于在SQL语句中添加条件判断。
<choose>
和<when>
标签:用于实现类似Java中的switch-case语句的逻辑判断。
<foreach>
标签:用于在SQL语句中遍历集合,并将集合中的元素拼接到SQL中。
<trim>
标签:用于在SQL语句中根据条件添加或删除SQL片段。
<where>
标签:用于动态添加WHERE子句,自动处理AND和OR关键字。
15.Mybatis中 插入用什么标签?
insert标签用于定义插入语句。
16.Mybatis 中insert 主键怎么返回?
在执行插入操作后,可以通过使用 <selectKey>
标签来获取插入记录的主键值。<selectKey>
标签需要放在 <insert>
标签内,并指定对应的主键生成策略。
示例:
```
<insert id="insertUser" parameterType="User"> <!-- 指定数据库支持自增长主键的方式 --> <selectKey resultType="int" keyProperty="id" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO users (username, email, age) VALUES (#{username}, #{email}, #{age}) </insert>
```
17.Mysql 关键字 limit 给定 2个参数时,这2个参数时什么意思?当前端传过来的页数 时,页数怎么转换成limit需要的参数?
当 LIMIT
后面跟着两个参数时,表示第一个参数为查询结果的起始行索引(从0开始计数),第二个参数为返回的行数。对于分页查询,可以使用 LIMIT
关键字来实现,通常配合前端传来的页数和每页显示的行数来计算
18.Redis 有哪些类型
-
字符串(String):最基本的数据类型,可以存储任意类型的数据,包括文本、数字、二进制数据等。常用于缓存、计数器、分布式锁等场景。
-
列表(List):有序、可重复的字符串列表。可以在列表的头部或尾部插入或删除元素,支持按索引获取元素,还可以实现简单的队列和栈功能。
-
集合(Set):无序、不重复的字符串集合。可以用于存储一组不重复的数据,支持交集、并集、差集等集合运算。
-
哈希(Hash):类似于关联数组,存储字段和值之间的映射关系。常用于存储对象的属性信息。
-
有序集合(Sorted Set):类似于集合,但每个元素都有一个分数(score)与之关联。元素根据分数进行排序,支持按分数范围获取元素,以及根据分数更新元素位置。
-
地理空间(Geo):存储地理位置信息的数据类型。可以用于存储地理位置坐标,并进行地理位置相关的查询操作。
19.mysql数据库事务4个属性
原子性:事务是一个完整的操作,事务的各步操作是不可分的(原子的);要么都执行,要么都不执行。
一致性:当事务完成时,数据必须处于一致状态。
隔离性:对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应该以任何方式依赖于或影响其他事务。
永久性:事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性。
20.Redis集群了解吗?什么是集群
Redis Cluster 是 Redis 的分布式实现,Redis 是一种内存数据结构存储。它允许您以确保高可用性和可扩展性的方式将数据拆分到多个节点(服务器)上。Redis Cluster 提供自动数据分片和复制来实现这些目标。
-
分区和分片:Redis集群将数据划分为分区,每个分区称为“槽”。使用哈希函数将密钥分布在不同的槽中,从而允许数据分布在多个节点上。
-
高可用性:Redis Cluster 为主节点提供自动故障转移。如果主节点发生故障,从节点将被提升为新的主节点,确保数据保持可用并且集群继续运行。
-
复制:Redis集群中的每个主节点可以有一个或多个从节点。从节点从主节点复制数据,提供数据冗余和容错。
-
自动重新分片:Redis Cluster 支持自动重新分片。当您在集群中添加或删除节点时,数据会自动重新分片以确保均衡分布。
-
一致性和可用性:Redis Cluster使用最终一致性的概念,这意味着它确保跨节点数据的最终同步,提供高可用性和分区容错性。
21.Redis主从了解吗?Redis 哨兵了解吗?
监控:监控主节点和从节点是否正常运行
提醒:当被监控的某个Redis节点出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
故障迁移:主数据库出现故障时会自动投票选择一台从数据库转换为主数据库
哨兵就是打辅助的,本身并不提供数据存储功能,能独立使用的方式只有两种,主从模式和集群模式
22.解释Redis击穿、穿透、雪崩?
1、缓存击穿:缓存击穿,也称为“缓存穿透”,是指针对缓存中不存在的特定键发出大量请求,并且所有这些请求最终都会命中底层数据源时,就会发生缓存击穿。例如,当缓存中的热门项目过期并且对该项目的后续请求导致缓存未命中时,就会发生这种情况。因此,后端系统可能会遇到流量突然激增,可能导致性能下降或过载。
解决方案:为了减轻缓存崩溃,您可以使用“缓存旁路”模式,其中应用程序首先检查缓存中是否存在密钥。如果没有,应用程序从后端获取数据,然后将其存储在缓存中。这样,后续对同一个key的请求就会在缓存中找到数据,减少后端的负载。
2、缓存穿透(Cache Penetration):当大量请求缓存中或后端数据源中不存在的键时,就会发生缓存穿透。这些请求本质上是无用的,因为没有数据可供检索,但它们仍然给系统带来不必要的负载。
缓存渗透的常见场景包括尝试访问不存在或无效数据的恶意请求,或者请求随机或不存在的密钥。
解决方案:为了防止缓存穿透,可以实现“布隆过滤器”或者在应用层使用简单的检查,在请求到达缓存或后端数据源之前过滤掉无效或不存在键的请求。
3、缓存雪崩:缓存雪崩是指大量缓存条目同时或短时间内过期的情况。当这种情况发生时,对这些键的所有请求都将错过缓存,并且后端系统将受到请求突然激增的打击。这可能会导致后端不堪重负,从而导致性能下降或系统故障。
当缓存对大量键使用相同的过期时间或者同时刷新和重新填充缓存时,经常会发生缓存雪崩。
解决方案:为了防止缓存雪崩,可以对缓存条目使用随机过期时间(抖动),这会随着时间的推移分散缓存条目的过期时间。此外,您可以实现缓存的高可用性和冗余,因此即使某些缓存节点发生故障,系统也可以继续服务来自其他可用节点的请求。
23.高并发情况 key失效 redis起不到很大的作用 请求落到数据库中 解决办法
-
热点数据预加载:在系统启动或低峰期,预先将热门数据加载到Redis缓存中。这样在高并发时,大部分请求可以直接从缓存中获取数据,减轻数据库的负载。
-
缓存数据永不过期:对于一些非热点数据或数据更新不频繁的情况,可以将其设置为永不过期。当有新数据更新时,再手动更新缓存,避免频繁的缓存失效操作。
-
设置短期过期时间和随机过期时间:对于热点数据,设置较短的过期时间,这样即使数据失效,下一次请求会尽快更新缓存。同时,引入随机过期时间,避免大量缓存同时失效导致数据库负载过大。
-
缓存穿透处理:对于一些不存在的或无效的数据请求,可以使用布隆过滤器或在应用层进行有效性校验,避免这类请求直接访问数据库。
-
分布式锁:使用分布式锁来避免缓存失效时大量请求同时访问数据库,只有一个请求可以执行数据库查询和更新操作,其他请求等待或返回缓存中的旧数据。
-
限流策略:在高并发情况下,可以使用限流策略,对请求进行限制,防止过多的请求落到数据库。
-
使用缓存中间件:考虑使用类似于Redis Cluster的缓存中间件,可以提供更高的可用性和容错性,减轻单个Redis节点的负担。
24.spring注解controller的作用
当组件属于控制层时,则使用@Controller注解
被Controller标记的类就是一个控制器,这个类中的方法,就是相应的动作
25.注解restcontroller ?
@RestController注解,代表返回的是json格式的数据,这个注解是Spring4之后新加的注解,原来返回json格式的数据需要@ResponseBody配合@Controller一起使用;
26.注解requestbody ?
主要用来接收前端传递给后端的json字符串中的数据;一般用post方式提交. 前端向传后端json数据
27.Autowired resource 区别?
都是bean注入时使用的
Autowired 是spring提供的注解;resource 是将J2EE本身提供的注解,需要导入包
Autowired 默认通过byType方式注入,resource 默认通过byName方式注入
Autowired 注入的对象需要在IOC容器中,否则需要加上required=false,表示忽略当前注入的bean,如果有直接注入,没有则跳过。
Autowired 作用在字段、setting方法以及构造器上;resource 作用在字段、setting上。
28.Autowired多个实现类怎么注入?
使用@Qualifier注解指定要注入的实现类的名称
使用@Primary注解指定一个默认的实现类,当有多个实现类时,优先使用@Primary注解的实现类。
使用Autowired注解的required属性为false,表示如果找不到要注入的实现类,就不注入。
29.批量删除
删除单个记录的基础上多写一个for循环语句。在for循环语句中依次执行单个删除的操作,最后达到批量删除的效果。
30.如何确保 Java 线程的同步?解释同步块和方法的概念。
确保线程的同步是为了保证多个线程在访问共享资源时不会产生冲突和数据不一致的情况。线程的同步是通过使用关键字synchronized
来实现的,它可以用于同步块和同步方法。
-
同步块(Synchronized Blocks): 同步块是用来标记一组代码,使得在同一时刻只有一个线程可以执行这些代码块。这种同步通过获取对象的监视器锁(或称为对象锁)来实现。只有一个线程可以持有该锁,其他线程必须等待该锁被释放才能进入同步块。这样可以确保同一时间内只有一个线程访问共享资源,避免竞争条件和数据不一致问题。
-
同步方法(Synchronized Methods): 同步方法是在方法声明时使用
synchronized
关键字,它表示整个方法是一个同步块,调用该方法时会自动获取对象的监视器锁。和同步块一样,同步方法保证同一时间内只有一个线程可以执行该方法。
31.什么是逻辑删除?
逻辑删除的主要目的是保留被删除数据的历史记录,同时避免物理删除可能带来的数据丢失或恢复困难。在某些业务场景下,特别是对于敏感数据或需要审计历史操作的情况下,逻辑删除是一个较为常见的数据处理方式。
32.Vue 常用指令
v-once指令、v-show指令、v-if指令、v-else指令、v-else-if指令、v-for指令、v-html指令、v-text指令、v-bind指令、v-on指令、v-model指令等等。
33.方法卸载哪个钩子函数中?
react组件的卸载阶段只有一个常用的钩子函数:componentWillUnmount()
在组件卸载(即从页面中消失)的时候触发,一般用来执行清理工作
34.vue点击事件怎么绑定?
vue提供了v-on事件绑定指令,用来辅助程序员为DOM元素绑定事件监听,原生的DOM对象有onclick
、oninput
等原生事件,在vue中为v-on:click
、v-on:input
等。
通过v-on
绑定的事件处理函数,需要在methods
节点中声明。
35.sping mvc注解
@RequestMapping:用来处理请求地址映射的注解,可用于映射一个请求或一个方法,可以用在类或方法上。
@Autowired:它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。
@ResponseBody:将java对象转为json格式的数据。
@RequestParam:将请求参数绑定到你控制器的方法参数上(是springmvc中接收普通参数的注解)
@PathVariable:映射 URL 绑定的占位符
@ModelAttribute:在这个控制器中不管其他任何一个方法被调用,都会执行。
36.说说你对Hashmap的理解?
HashMap是基于哈希表实现的,每一个元素是一个key-value对,无序,不可重复。
HashMap线程不安全,只是用于单线程环境下,多线程环境下可以采用concurren并发包下的concurrentHashMap。
HashMap 实现了Serializable接口,因此它支持序列化,实现了Cloneable接口,能被克隆。
HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
37.什么是跨域?
协议、域名、端口
定义:当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。
38.怎么解决跨域?
JSONP方式解决跨域:jsonp的原理就是利用了script标签不受浏览器同源策略的限制,然后和后端一起配合来解决跨域问题的。
CORS方式解决跨域:cors是跨域资源共享,是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(域,协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。服务端设置了Access-Control-Allow-Origin就开启了CORS,所以这种方式只要后端实现了CORS,就解决跨域问题,前端不需要配置。
搭建Node代理服务器解决跨域:因为同源策略是浏览器限制的,所以服务端请求服务器是不受浏览器同源策略的限制的,因此我们可以搭建一个自己的node服务器来代理访问服务器。
Nginx反向代理解决跨域:nginx通过反向代理解决跨域也是利用了服务器请求服务器不受浏览器同源策略的限制实现的。
postMessage方式解决跨域:window.postMessage() 方法可以安全地实现跨源通信,此方法一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
Websocket方式解决跨域:WebSocket 规范定义了一个在 Web 浏览器和服务器之间建立“套接字”连接的 API。客户端和服务器之间存在持久连接,双方可以随时开始发送数据。
39.Mysql 中的视图?
Creat View 视图名(你要存入的列名称)
视图,虚拟表,从一个表或多个表中查询出来的表,作用和真实表一样,包含一系列带有行和列的数据。视图中,用户可以使用SELECT语句查询数据,也可以使用INSERT,UPDATE,DELETE修改记录,视图可以使用户操作方便,并保障数据库系统安全。
40.外键级联删除?
可以通过设置外键约束,指定ON DELETE CASCADE选项来实现 级联删除 。 具体实现步骤为:先创建外键,指定参照表和参照字段,然后在ON DELETE后面添加CASCADE关键字即可。
41.查询最大年及的个人信息?
Max(age)或查出年龄倒叙排序
/**年龄最大=出生日最小
SELECT*FROM Tb_StudentWHERE Birthday=(SELECT MIN(Birthday) FROM Tb_Student)
年龄最小=出生日最大 SELECT*FROM Tb_Student WHERE Birthday=(SELECT MAX(Birthday) FROM Tb_Student)**/
42.外键级联删除?
可以通过设置外键约束,指定ON DELETE CASCADE选项来实现 级联删除 。 具体实现步骤为:先创建外键,指定参照表和参照字段,然后在ON DELETE后面添加CASCADE关键字即可。
43.redis数据类型?
Redis的9种数据类型
1. string:最基本的数据类型,二进制安全的字符串,最大512M。
2. list:按照添加顺序保持顺序的字符串列表。
3. set:无序的字符串集合,不存在重复的元素。
4. sorted set:已排序的字符串集合。
5. hash:key-value对的一种集合。
6. bitmap:更细化的一种操作,以bit为单位。
7. hyperloglog:基于概率的数据结构。 # 2.8.9新增
8. Geo:地理位置信息储存起来, 并对这些信息进行操作 # 3.2新增
9. 流(Stream)# 5.0新增
44.Redis中set常用? 用来存储的内容是什么?为什么存这个内容?
Set 是 redis 中的单列集合,满足下列特点
1.不保证有序性
2.保证元素唯一(可以保证元素是否唯一)
3.求交集、并集、差集
为了查询效率和唯一性,Set 采用 HT 编码(Dict),Dict 中的 key 用来存储元素,value 统一为 null
当存储的所有数据都是整数,并且元素数量不超过 set-max-intset-entries(默认值为 512 ) 时,Set 会采用IntSet编码,以节省内存
与List类似是一个列表功能,但Set是自动排重的,当需要存储一个列表数据,又不希望出现重复数据 时,Set是一个很好的选择。
Set是String类型的无序集合,它底层其实是一个value为null的hash表,所以添加、删除、查找的时间 复杂度都是O(1).
45.初始化页面加载函数?
一般初始化的执行的函数,都是
document.addEventListener('DOMContentLoaded', function (event) {
// 这里面执行代码、调用其他函数
})
这样会在浏览器加载好DOM后才执行,不过IE不支持
IE的话可以用window.load = function () {}
上jQuery就$(function() {
// 这里面执行代码、调用其他函数
})
46.简述Number?
Number
是 JavaScript 中的一个内置对象,它用于处理数值类型的数据。Number
对象提供了许多用于数值操作和转换的方法。同时,数值类型的原始值(即数字)也可以通过 Number
构造函数来创建 Number
对象。
在 JavaScript 中,有两种表示数值的方式:原始数值和 Number
对象。
-
原始数值: 原始数值是指直接以数字形式表示的数值,例如:
5
,10.5
,-3
, 等等。这些原始数值没有任何方法或属性,仅用于进行数值计算和比较。 -
Number
对象:Number
对象是通过Number
构造函数创建的对象,它可以用于执行与数值相关的操作。例如,可以使用Number
对象的方法来进行数值的转换、格式化和操作。
以下是一些 Number
对象的常用方法:
-
Number.parseInt()
:将字符串转换为整数。 -
Number.parseFloat()
:将字符串转换为浮点数。 -
Number.isNaN()
:检查一个值是否为NaN。 -
Number.isFinite()
:检查一个值是否为有限数值。 -
Number.isInteger()
:检查一个值是否为整数。 -
Number.toFixed()
:将数值转换为指定小数位数的字符串表示。 -
Number.toPrecision()
:将数值转换为指定有效位数的字符串表示。 -
Number.toString()
:将数值转换为字符串。
47.Java 中如何中断线程?解释一下interrupt()
方法。
-
在线程处于阻塞状态时中断:当线程调用
wait()
、sleep()
、join()
等阻塞方法时,如果另一个线程调用了该线程的interrupt()
方法,被阻塞的线程会抛出InterruptedException
异常,从而提前结束阻塞状态。 -
设置中断标志:线程可以通过
isInterrupted()
方法来检查自身的中断标志,从而根据情况自行决定是否中断执行。
48.解释 Java 中守护线程的概念以及何时使用它们。
-
它们被用于为其他线程提供服务,通常是在后台执行一些任务或执行周期性的工作,例如垃圾回收、内存管理等。
-
守护线程通常用于支持性工作,当应用程序中所有的非守护线程都结束时,守护线程会自动终止。因此,它们不应该执行需要确保完成的重要任务,因为无法保证它们能在应用程序关闭之前执行完毕。
-
守护线程的创建方法与普通线程相同,只需在调用
start()
方法之前,通过setDaemon(true)
将线程设置为守护线程。
49.VUE中v-on v-bind v-model的区别?
v-bind:属性绑定(简写:), v-on:事件绑定(简写@), v-model:双向绑定(简写v-model(v-model:value="model" v-model="model"))。
v-bind与v-model都是绑定vue中data中的属性的,他们最主要的区别是v-bind的绑定只是单向的,他会将data中的数据投影到绑定的地方,在被绑定的地方对数据修改时,data中的原始数据是不会改变的,而v-model的绑定是双向的,不仅将data中的数据对标签内进行绑定,还会将标签中的数据反向绑定到data中,标签数据改变后data中的数据也会同步改变。
v-on绑定的是事件(函数)是vue中methods中的数据,触发v-on绑定,就会执行其所绑定的事件。
50.怎么判断标签的显示隐藏?
浏览器标签页被隐藏或显示的时候会触发visibilitychange事件。
51.mvvm概念
MVVM是Model-View-ViewModel的简写。它本质上就是MVC的改进版。MVVM模式有助于将应用程序的业务和表示逻辑与用户界面 (UI) 清晰分离。 保持应用程序逻辑和UI之间的清晰分离有助于解决许多开发问题,并使应用程序更易于测试、维护和演变。 它还可以显著提高代码重用机会,并允许开发人员和UI设计人员在开发应用各自的部分时更轻松地进行协作。
52.axios异常怎么捕获?
通过 axio 的 interceptors 做拦截处理,把各类异常情况包装成统一的结构输出。
另外提供包装器方法,不同的业务部分调用不用的包装器处理。
53.线程创建方式?
继承Tread类,重写run方法
实现Runnable接口,实现run方法
实现callable接口,实现call方法,获取线程执行结果。
54.什么是数据库事务?
Commit rollback
数据库事务是指一个逻辑工作单元中执行的一系列操作,要么完全执行,要么都不执行
55.数据库索引知道几种?
明 暗 用于加快查询
普通索引 唯一索引 全文索引 单例索引(多利索引) 组合索引(最左前缀)
56.char和varchar的区别
char的长度是固定的varchar是可变的,char每次修改的数据长度相同效率高,varchar每次修改的数据长度不同,效率低
57.模糊查的关键字是?%和 _的区别是什么?
关键字:Like
%
:百分号是用于匹配任意字符(包括零个字符)的通配符。在模糊查找中,可以将 %
放在需要匹配任意字符的位置,表示可以匹配任意长度的字符序列。
_
:下划线是用于匹配单个字符的通配符。在模糊查找中,可以将 _
放在需要匹配单个字符的位置,表示可以匹配任意一个字符。
58.object常用方法?
-
Object.keys(obj)
:返回一个包含对象中所有可枚举属性的数组。 -
Object.values(obj)
:返回一个包含对象中所有可枚举属性的值的数组。 -
Object.entries(obj)
:返回一个包含对象中所有可枚举属性的键值对(数组形式)的数组。 -
Object.assign(target, ...sources)
:将一个或多个源对象的属性合并到目标对象中,并返回合并后的目标对象。 -
Object.hasOwnProperty(prop)
:判断对象是否具有指定的属性,返回一个布尔值。 -
Object.getOwnPropertyNames(obj)
:返回一个包含对象中所有属性(包括不可枚举属性)的数组。 -
Object.getOwnPropertyDescriptor(obj, prop)
:返回一个对象,其中包含指定属性的属性描述符。 -
Object.seal(obj)
:封闭对象,使其现有属性不可删除,但属性的值可以修改。 -
Object.freeze(obj)
:冻结对象,使其现有属性不可删除和修改。 -
Object.is(obj1, obj2)
:比较两个值是否相同,类似于===
运算符,但可以正确处理NaN
和-0
。 -
Object.entries(obj)
:返回一个包含对象中所有可枚举属性的键值对(数组形式)的数组。 -
Object.fromEntries(entries)
:将一个键值对的数组转换为一个对象。 -
Object.create(proto, propertiesObject)
:使用指定的原型对象和属性描述符创建一个新对象。
59.Java中的自动装箱和拆箱是什么?如何实现这些功能?
-
自动装箱(Autoboxing): 自动装箱是指将基本数据类型转换为对应的包装类对象。例如,将
int
类型转换为Integer
对象。 -
自动拆箱(Unboxing): 自动拆箱是指将包装类对象转换为对应的基本数据类型。例如,将
Integer
对象转换为int
类型。
60.重写在什么情况下发生?什么是重载?
重写发生在子类继承自父类的情况下。当子类定义一个与父类中已有方法具有相同名称、参数列表和返回类型的方法时,子类的方法将覆盖(或重写)父类的方法。重写后,当通过子类对象调用该方法时,实际执行的是子类中的方法,而不是父类中的方法。这使得子类可以根据自己的需求来重新实现继承自父类的方法。
重载发生在同一个类中,当一个类中有多个方法拥有相同的名称但具有不同的参数列表时,这些方法就被称为方法的重载。重载的方法在参数数量、类型或顺序上必须有所不同,否则编译器将无法区分这些方法,导致编译错误。在调用重载的方法时,编译器会根据传入的参数的数量和类型,自动选择合适的方法来执行。
61.mysql聚合函数?
-
COUNT()
:用于统计满足条件的行数。 示例:SELECT COUNT(*) FROM table_name;
-
SUM()
:用于计算数值列的总和。 示例:SELECT SUM(column_name) FROM table_name;
-
AVG()
:用于计算数值列的平均值。 示例:SELECT AVG(column_name) FROM table_name;
-
MIN()
:用于找出数值列中的最小值。 示例:SELECT MIN(column_name) FROM table_name;
-
MAX()
:用于找出数值列中的最大值。 示例:SELECT MAX(column_name) FROM table_name;
-
GROUP_CONCAT()
:用于将一列中的值连接成一个字符串,可选用ORDER BY
对结果进行排序。 -
GROUP BY
:用于按照某一列或多列的值对结果进行分组,通常与聚合函数结合使用。
62.list中长度获取?
在 Java 中,list
是通过 ArrayList
或其他类实现的。可以使用 size()
方法获取 ArrayList
的长度。
63.数组怎么获取长度?
数组名.lenght 没括号是属性 有括号叫方法
64.分页关键字是?
-
LIMIT
:用于限制查询结果返回的行数。它需要配合一个数值参数,表示返回的行数的上限。 -
OFFSET
:用于设置查询结果的偏移量,即从第几行开始返回结果。它也需要配合一个数值参数,表示查询结果的偏移量。
65.int转string? string转int? 分别怎么转换?用什么方法
int转string:
Java:使用 String.valueOf()
方法或直接将整数加上空字符串(隐式转换)。
JavaScript (Node.js):使用 toString()
方法或将整数加上空字符串(隐式转换)。
string转int:
Java:使用 Integer.parseInt()
方法。
JavaScript (Node.js):使用 parseInt()
函数。
66.Mysql 数据库中怎么数据调优?
-
索引优化:
-
确保表中频繁查询的列添加了合适的索引,这可以加快查询速度。但是要注意不要过度索引,因为索引会增加插入和更新操作的开销。
-
使用复合索引来覆盖多个查询条件,这样可以减少索引的数量并提高查询效率。
-
定期进行索引维护和优化,删除不再使用的索引。
-
-
查询优化:
-
编写高效的SQL查询语句,避免全表扫描和不必要的数据查询。
-
避免在查询中使用
SELECT *
,而是只选择需要的列,以减少数据传输和内存使用。 -
使用EXPLAIN命令分析查询执行计划,以找出潜在的性能问题。
-
-
缓存优化:
-
合理使用数据库缓存,如MySQL的查询缓存或外部缓存工具(如Redis),可以减少重复查询的开销。
-
使用适当的缓存策略,避免缓存数据过期或占用过多内存。
-
-
表结构优化:
-
合理设计数据库表结构,避免冗余数据和不必要的字段,减少数据存储空间。
-
使用合适的数据类型,避免使用过大或不恰当的数据类型,降低存储和内存开销。
-
-
批量操作优化:
-
将多个单条数据操作合并为批量操作,可以减少与数据库的通信次数,提高性能。
-
-
分区表:
-
对于大型表,可以使用分区表技术将表分割成多个独立的子表,提高查询和维护的效率。
-
-
定期数据清理:
-
定期清理无用数据,避免数据量过大影响性能。
-
-
硬件和配置优化:
-
使用性能更好的硬件设备,如SSD硬盘和更大内存。
-
调整数据库相关的配置参数,如连接池大小、缓冲区大小等,以适应实际负载需求。
-
67.什么是数据库索引?
-
提高查询速度:通过使用索引,数据库系统可以直接定位到索引列上的特定值,而不是遍历整个表来查找数据。这样可以大大加快查询的速度,特别是在大型数据表中。
-
加速排序:当数据库查询包含了
ORDER BY
子句时,如果查询中使用了索引列,数据库可以利用索引的排序顺序,避免执行额外的排序操作,从而提高排序的效率。 -
加速连接操作:当数据库查询涉及到多个表的连接操作时,如果连接的列上有索引,可以显著减少连接操作的时间。
-
约束和唯一性:在数据库中,可以使用索引来创建唯一性约束,确保某列的值唯一。这样可以防止重复数据的插入。
68.什么是Java的反射(Reflection)?如何使用反射来获取类的信息和动态调用方法?
Java的反射(Reflection)是一种在运行时获取、检查和操作类或对象的能力。通过反射,我们可以在程序运行时动态地获取类的信息(例如类的字段、方法、构造函数等),创建类的对象,调用类的方法,以及修改类的字段值等。
在Java中,反射是通过java.lang.reflect
包中的一组类来实现的,主要涉及以下几个重要的类:
-
Class
类:代表一个Java类的类对象。通过Class
类的实例,可以获取类的信息。 -
Field
类:代表类的成员变量(字段)。 -
Method
类:代表类的方法。 -
Constructor
类:代表类的构造函数。
使用反射来获取类的信息和动态调用方法,可以按照以下步骤进行:
-
获取类的Class对象:
-
使用类的静态属性
class
,例如:Class.forName("packageName.ClassName")
。 -
使用对象的
getClass()
方法,例如:object.getClass()
。
-
-
获取类的成员变量(字段):
-
使用
Class
类的getDeclaredFields()
方法,可以获取所有声明的字段,包括私有字段。 -
使用
Class
类的getField(String name)
方法,可以获取指定名称的公共字段。
-
-
获取类的方法:
-
使用
Class
类的getDeclaredMethods()
方法,可以获取所有声明的方法,包括私有方法。 -
使用
Class
类的getMethods()
方法,可以获取所有公共方法,包括从父类继承的方法。
-
-
获取类的构造函数:
-
使用
Class
类的getDeclaredConstructors()
方法,可以获取所有声明的构造函数,包括私有构造函数。 -
使用
Class
类的getConstructors()
方法,可以获取所有公共构造函数。
-
-
创建类的对象:
-
使用
Class
类的newInstance()
方法,可以创建类的实例。
-
-
调用类的方法:
-
使用
Method
类的invoke(Object obj, Object... args)
方法,可以调用类的方法。第一个参数是方法所属的对象(如果方法是静态的,则可以传入null
),后面的参数是方法的参数。
-
69.list集合作用?
-
存储一组数据:List 可以用于存储多个元素,这些元素可以是不同类型的数据(如整数、字符串等),也可以是复杂的自定义对象。
-
动态扩容:List 可以根据需要动态地增加元素,当 List 中的元素数量超过其初始容量时,它会自动扩容,以容纳更多的元素。
-
遍历和访问元素:List 允许按照索引或迭代器来遍历其中的元素,并可以通过索引来访问特定位置的元素。
-
元素重复:List 允许存储重复的元素,即同一个元素可以在 List 中出现多次。
-
数据排序:List 提供了排序方法,可以对其中的元素按照指定规则进行排序。
-
数据增删:List 提供了添加和删除元素的方法,允许在任意位置插入新元素,或删除指定位置或指定元素。
-
数据查找:List 提供了查找元素的方法,可以根据元素值或条件查找对应的元素。
70.对象之间的关系有几种?
-
关联(Association): 关联表示对象之间的一种关系,通常是一种拥有的关系。一个对象可以与其他对象相关联,这意味着一个对象持有对另一个对象的引用。关联可以是单向的或双向的,它们可以是一对一、一对多或多对多的关系。例如,一个学生对象可以关联一个班级对象,表示学生所属的班级。
-
聚合(Aggregation): 聚合表示的是整体与部分之间的关系,即一个对象包含其他对象。在聚合关系中,一个对象可以包含另一个对象,但被包含对象可以独立于整体对象存在。聚合是一种弱关系,被包含的对象可以属于多个整体对象。例如,一个学院对象可以聚合多个学生对象,表示学院包含多个学生。
-
组合(Composition): 组合是聚合关系的特殊形式,它表示的是整体与部分之间的强关系。在组合关系中,一个对象包含其他对象,并且被包含对象的生命周期与整体对象相依赖。如果整体对象被销毁,那么其中的部分对象也会被销毁。例如,一个汽车对象可以组合多个车轮对象,车轮对象的生命周期与汽车对象紧密相连。
-
继承(Inheritance): 继承表示的是一个对象从另一个对象继承特性和行为。在继承关系中,一个对象称为子类或派生类,它继承了另一个对象的属性和方法,称为父类或基类。继承允许子类拥有父类的特性,并可以根据需要扩展或重写父类的方法。继承是面向对象编程中的一种重要特性,它提供了代码重用和多态性的机制。
71.arraylist length获取长度?
在 Java 中,ArrayList
是通过 java.util.ArrayList
类实现的。要获取 ArrayList
的长度,可以使用 size()
方法。
72.for,增强for 区别是?
for
循环是一种传统的循环结构,通常用于指定一个循环变量的初始值、循环条件和每次循环后更新循环变量的表达式。它适用于遍历数组或集合的索引或者指定的范围。
增强 for
循环是一种简化版的循环结构,它在遍历数组或集合时更加简洁和直观。增强 for
循环遍历集合中的每个元素,并自动取出当前元素的值赋给循环变量,不需要显式指定循环变量的索引或范围。
73.spring的注入方式
-
构造函数注入(Constructor Injection): 通过构造函数来注入依赖,即在类的构造函数中接收需要注入的依赖对象。在类实例化时,Spring 容器会自动查找匹配的依赖并通过构造函数进行注入。
-
Setter 方法注入(Setter Injection): 通过 setter 方法来注入依赖,即在类中定义 setter 方法接收需要注入的依赖对象。Spring 容器会自动调用相应的 setter 方法进行注入。
-
字段注入(Field Injection): 直接在字段上使用
@Autowired
注解进行注入,Spring 容器会自动将依赖对象注入到字段中。这种方式通常需要确保字段的访问级别为private
或protected
。 -
接口注入(Interface Injection): 通过接口定义需要注入的依赖,然后在实现类中实现该接口,并由 Spring 容器自动查找并注入依赖对象。
-
自动扫描注入: Spring 可以自动扫描指定包下的组件,并自动进行依赖注入。通过在配置文件中配置
<context:component-scan>
或使用@ComponentScan
注解,Spring 将自动识别被@Component
或相关注解标记的类,并完成依赖注入。
74.创建线程的方式
Java 中的 Thread 类: 在 Java 中,可以通过继承 Thread 类并重写其 run() 方法来创建线程。然后,调用线程对象的 start() 方法来启动线程。
Java 中的 Runnable 接口: 另一种在 Java 中创建线程的方式是实现 Runnable 接口,并将其实例作为参数传递给 Thread 类的构造函数。然后,调用线程对象的 start() 方法来启动线程。
75.什么是Java的序列化(Serialization)和反序列化?
Java的序列化(Serialization)是指将对象转换为字节序列的过程,以便可以将这些字节序列保存到文件、内存或网络传输,并在需要的时候重新将字节序列转换回原始对象。反序列化(Deserialization)则是将字节序列重新转换为对象的过程。
序列化和反序列化在Java中是通过实现java.io.Serializable
接口来完成的。要使一个类可以被序列化,只需将该类实现Serializable
接口,该接口是一个标记接口,不包含任何方法,它只是用来标识该类可以被序列化。
要实现序列化和反序列化,可以使用Java提供的ObjectOutputStream
和ObjectInputStream
类,它们分别用于将对象写入输出流和从输入流中读取对象。
76.Java中的IO流是什么?解释字节流和字符流的区别。
-
字节流(Byte Stream): 字节流以字节为单位进行输入和输出,适用于处理二进制数据或字节数据。字节流主要由两个基类组成:
InputStream
和OutputStream
。它们的子类用于实现不同的输入和输出操作,比如读写文件、网络连接等。-
InputStream
:用于从输入源(如文件、网络)读取字节数据。 -
OutputStream
:用于向输出目标(如文件、网络)写入字节数据。
字节流适用于处理非文本类型的数据,如图片、视频、音频等,以及在处理纯二进制数据时。
-
-
字符流(Character Stream): 字符流以字符为单位进行输入和输出,适用于处理文本数据。字符流主要由两个基类组成:
Reader
和Writer
。它们的子类用于实现不同的字符输入和输出操作,比如读写文本文件、处理控制台输入等。-
Reader
:用于从输入源(如文件、网络)读取字符数据。 -
Writer
:用于向输出目标(如文件、网络)写入字符数据。
字符流适用于处理文本类型的数据,它们在读写文本文件时更为方便,因为字符流会考虑字符编码和字符集的问题,能够正确地处理Unicode字符和特定字符集的数据。
-
77.解释Java中的equals()和hashCode()方法的作用。
equals()方法: equals()
方法用于比较两个对象是否相等。在Object
类中,equals()
方法默认是使用==
运算符进行引用比较,即判断两个对象是否是同一个引用。但通常情况下,我们希望对自定义类的对象进行内容比较,而不仅仅是引用比较。因此,我们需要在自定义类中重写equals()
方法来定义对象的相等性规则。
重写equals()
方法应该满足以下几个条件:
-
自反性:对于任意非空引用x,x.equals(x)应该返回true。
-
对称性:对于任意非空引用x和y,如果x.equals(y)返回true,则y.equals(x)也应该返回true。
-
传递性:对于任意非空引用x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,则x.equals(z)应该返回true。
-
一致性:对于任意非空引用x和y,如果对象中的信息没有被修改,则多次调用x.equals(y)应该返回相同的结果。
-
非空性:对于任意非空引用x,x.equals(null)应该返回false。
hashCode()方法: hashCode()
方法返回对象的散列码(哈希码),它是一个用于快速查找的整数值。在Java中,散列码被用于数据结构如散列表(HashMap、HashSet等)来快速定位对象。
hashCode()
方法的默认实现是将对象的内存地址转换为一个整数值,因此对于不同的对象,它们的散列码通常是不同的。但是,如果我们重写了equals()
方法,我们也应该重写hashCode()
方法,以保证相等的对象有相同的散列码,这是为了遵守equals()
和hashCode()
的约定:如果两个对象相等,它们的散列码必须相等。
在重写hashCode()
方法时,通常会使用对象的字段来计算散列码,确保相等的对象有相同的散列码,尽可能减少散列冲突。
78.什么是Java内存模型(Java Memory Model,JMM)?如何实现线程之间的通信?
Java内存模型(Java Memory Model,JMM)是Java程序中多线程并发访问共享内存的规范。它定义了在多线程环境下,线程如何与主内存和本地内存进行交互,以及如何确保线程之间的可见性、有序性和原子性。
在JMM中,每个线程都有自己的本地内存,用于存储主内存中的共享变量的副本。线程在执行过程中,会将共享变量从主内存中拷贝到本地内存中进行读写操作,然后再将修改后的值刷新回主内存。
JMM确保了以下几个重要的特性:
-
可见性(Visibility):一个线程对共享变量的修改对其他线程是可见的。当一个线程修改了共享变量的值,它必须将修改后的值刷新到主内存,其他线程读取共享变量时,会从主内存中读取最新值。
-
有序性(Ordering):JMM保证程序执行的顺序按照代码的顺序执行。但是,由于处理器的优化和指令重排序等原因,线程可能会以不同的顺序执行部分代码,但是JMM会确保最终的执行结果是和代码顺序一致的。
-
原子性(Atomicity):对于简单的读写操作(比如读写一个int类型的变量),JMM保证了原子性,即一个线程的读写操作是不可分割的。对于复合操作(如i++),如果没有同步措施,可能会发生竞态条件和线程安全问题。
线程之间的通信可以通过以下方式实现:
-
共享变量(Shared Variables):线程之间通过读写共享变量来进行通信。要确保共享变量的可见性和一致性,需要使用同步机制(如
synchronized
关键字或volatile
修饰符)来保证线程对共享变量的读写操作是安全的。 -
volatile关键字:
volatile
修饰的共享变量具有可见性,它会告诉JMM不要对该变量进行优化,每次读取和写入都直接操作主内存,不使用本地内存。这样可以确保共享变量的修改对其他线程是立即可见的。 -
synchronized关键字:使用
synchronized
关键字可以实现对临界区的互斥访问,保证多个线程对共享资源的读写操作是原子性的。当一个线程获得了某个对象的锁时,其他线程将无法访问这个对象的synchronized
方法和代码块,从而保证线程之间的协调和通信。 -
Lock机制:除了
synchronized
关键字外,Java还提供了Lock
接口及其实现类,如ReentrantLock
,用于实现更灵活和高级的线程互斥访问机制。
79.Java中的多线程同步机制有哪些?如何避免线程安全问题?
-
synchronized关键字: 使用
synchronized
关键字可以实现对临界区的互斥访问,确保多个线程对共享资源的读写操作是原子性的。当一个线程获得了某个对象的锁时,其他线程将无法访问这个对象的synchronized
方法和代码块,从而保证线程之间的协调和通信。 -
volatile关键字: 使用
volatile
修饰的共享变量具有可见性,它会告诉Java虚拟机不要对该变量进行优化,每次读取和写入都直接操作主内存,不使用本地内存。这样可以确保共享变量的修改对其他线程是立即可见的。 -
Lock机制: Java提供了
Lock
接口及其实现类,如ReentrantLock
,用于实现更灵活和高级的线程互斥访问机制。Lock
接口提供了lock()
和unlock()
方法来手动获取和释放锁,可以实现更灵活的锁定和解锁操作。 -
原子类: Java中的
java.util.concurrent.atomic
包提供了一组原子类,如AtomicInteger
、AtomicLong
等,它们提供了一些原子操作,能够保证对共享变量的操作是原子的,从而避免竞态条件。 -
线程安全的集合类: Java中的
java.util.concurrent
包提供了一些线程安全的集合类,如ConcurrentHashMap
、CopyOnWriteArrayList
等,它们内部实现了线程同步,可以安全地用于多线程环境。 -
使用ThreadLocal:
ThreadLocal
类可以让每个线程都拥有自己的局部变量,从而避免线程间的共享资源竞争。
80.什么是Java的注解处理器(Annotation Processor)?如何自定义一个注解处理器?
-
定义注解: 首先,需要定义一个自定义的注解。注解使用
@interface
关键字来声明,可以在注解中定义属性,用于传递参数。 -
编写注解处理器: 创建一个注解处理器类,并继承
AbstractProcessor
。在该类中,需要重写process
方法,该方法会在编译时被调用,用于处理源代码中的注解。 -
注册注解处理器: 在
META-INF/services
目录下创建一个名为javax.annotation.processing.Processor
的文件,其中列出你的注解处理器的全限定类名。 -
使用注解处理器: 在你的项目中使用自定义的注解,并在编译时让Java编译器调用你的注解处理器。
-
注解处理器的使用方式有多种,可以在Maven或Gradle中配置编译插件,也可以通过命令行调用Java编译器,并指定注解处理器。在调用注解处理器时,Java编译器会将所有标注了特定注解的类传递给注解处理器,并执行其中的处理逻辑。
81.Mysql 存储引擎有哪些
InnoDB 基本用这个
MyISAM
Memory
CSV
82.一个表选择哪些列创建索引
首先要看查询条件。查询条件(where)里有的列,才考虑创建索引。
高频率查询语句,查询条件里有的列,优先创建索引。
当然,创建索引,还要考虑这一列数据的区分度是否够高。单纯的 性别 、状态 这样的列,数据区分度不够,不适合做单列索引。可以考虑和其它字段组合,创建联合索引(多列索引)
一个表,并不适合创建过多的索引。索引太多,影响插入、修改的性能。
83.如何进行sql优化
1. 可以开启慢sql,然后查看慢sql日志,找出需要优化的sql语句
2. 通过explain 命令,来分析sql的执行情况,看看是否命中了索引,或者使用的是什么类型的索引
84.如何判断索引是否命中(explain 查询计划)
使用查询计划 explain 可以查看 索引命中情况
explain的结果:
type:all 说明全表扫描
key:为空,说明没有使用索引
85.如何排查效率低的sql
使用explain(查询计划),查看 当前sql执行情况
通过 type 列,来看索引的使用情况。
86.什么是聚簇索引(聚集索引)
Innodb存储引擎主键索引用的就是聚集索引。
索引文件和数据文件,是同一个文件。
87.事务隔离级别
读未提交
读已提交
可重复读 (默认)
串行
88.java的方法里,参数传递是值传递吗
基本数据类型,是值传递。相当于拷贝一份数据传递到方法里。
对于引用类型,可以理解为地址传递,传入方法内部的变量,指向的还是同一个对象。并没有拷贝新的对象传到方法内部。
89.java异常体系结构
最顶层的类是 Throwable
Throwable 下面是 Exception 和 Error
Error 一般是系统错误,比如 内存不足 等,我们就算catch到了,也无法解决。
Exception 一般是程序的业务问题,catch到了,可以进行响应解决。
Exception 分为 RuntimeException 和 其它异常(受检异常)
受检异常:需要进行处理。try catch 或者 方法上 加 throws
受检异常的例子:SqlException IOException
RuntimeException: 空指针异常 数组下表越界异常 非法参数异常
90.深拷贝和浅拷贝
对一个对象进行拷贝时:
不仅将对象拷贝了,还把对象所有属性都进行拷贝,那么就是深拷贝。
如果对象的属性并没有进行拷贝,只是拷贝了对象本身,那就是浅拷贝
java Object类的 clone (克隆)方法,实了浅拷贝
实现深拷贝的思路:
自己写代码实现:
递归的将对象里所有的引用类型的属性进行clone,最终让所有的属性都拷贝一份。
也可以借助java对象的序列化来实现,将对象序列化,然后进行反序列化。
也可以将java对象序列化成json字符串,然后再反序列化回java对象。
91.集合类的体系结构
Collection 接口:List 接口 和 Set接口
List接口 实现类有: ArrayList LinkedList
Set接口 实现类有: HashSet LinkedHashSet TreeSet
Map接口实现类有: HashMap LinkedH·ashMap TreeMap
遍历顺序问题:
HashSet 和 HashMap 进行遍历,是没有顺序的。也就是说,不保证遍历出来的顺序和放入的顺序是一样的。
如果你想要保证顺序,就需要使用 LinkedHashSet 或者 LinkedHashMap
equals 和 hashcode:
一个对象,如果要放入 HashSet 或者 LinkedHashSet, 这个对象必须重写 equals方法和equals方法,才会有去重的效果。
按照大小顺序进行存储:
如果想要 Set 或者 Map 能够按照大小顺序排序,那么 对象需要重写 Compareable接口。
当然,对象不重写Compareable接口的话,也可以在new出TreeSet 或者 TreeMap的时候,提供一个Comparator,把对象大小比较的规则,告诉 TreeSet 或者 TreeMap
92.redis的持久化策略
RDB:快照
执行RDB时,会将redis内存里的数据,全部持久化到硬盘中。
如果redis里数据量很大,可想而知,这个持久化会很慢,而且非常耗费服务器的资源。
AOF:日志
AOF 是 redis将所有执行过的更新数据的操作的指令记录下来,然后存到一个日志文件中。将来,如果redis宕机了,可以通过重放日志指令的方式,让数据再次回来。
优缺点:
RDB:没办法频繁操作。一般用于 手动 备份数据。
AOF 写日志,刚开始只是将日志写在内存缓冲区中,通常会配置成每秒种进行一个词刷盘操作。所以,如果没有及时刷盘,那么缓存在内存缓冲区的日志指令,就会丢失。但是,最多只会丢掉最近1秒的数据。
项目种,主要是通过开启AOF来保证持久化的。RDB主要用在定期备份数据上。
93.如何保证redis 和 mysql的数据一致
有以下方案:
1. 修改数据的时候,同时修改缓存 双写
2. 先删除数据,再修改数据库,等一会,再删除缓存 延时双删
3. 使用canal,监控mysql bin log,然后更新redis