2022-06-07
1、数组和集合的区别
答:
(1)数组长度不可变化而且无法保存具有映射关系的数据;
集合类用于保存数量不确定的数据,以及保存具有映射关系的数据。
(2)数组元素既可以是基本类型的值,也可以是对象;集合只能保存对象。
2、springboot如何处理异常
答:
1)创建一个类集中处理异常@ControllerAdvice
2)出现对应的异常会进入对应的方法进行处理@ExceptionHandler(value = java.lang.Exception.class)
3)返回结果
3、equals和==区别
答:
== 的作用:
基本类型:比较的就是值是否相同
引用类型:比较的就是地址值是否相同
equals 的作用:
引用类型:默认情况下,比较的是地址值。
4、单例模式及懒汉饿汉模型
答:
单例模式:一个类只有一个对象实例
饿汉模型:一个单例类还没被使用,它的单例对象就已经创建好了。使用static修饰成员变量,在类创建时就创建对象。不存在线程安全问题,但可能会造成资源浪费。
当程序启动后一定会用到此类,我们选择饿汉模式
懒汉模型:等到使用这个单例类时才创建单例对象。使用static修饰成员变量,在类被调用时创建对象。但存在线程安全问题
当我们使用一些工具类,优先考虑使用懒汉模式,可避免资源被提前加载到内存中
运行结果
5、Arraylist自定义排序
答:
ArrayList中存在sort排序方法,只要你实现了Comparator的接口,就可以按照自定义的排序业务实现排序。
使用Collections.sort()传入ArrayList和自己实现Commparator接口的类的对象,实现自定义排序
Collections.sort()升序排列 Collections.sort()降序排列使用List.sort()传入自己实现Commparator接口的类的对象,实现自定义排序
Java7,List并没有sort方法,请使用Collections.sort()
List.sort()降序排列
6、重写equals要不要重写hashcode
答:
当我们需要使用自己定义的类作为HashMap中的key的时候,或者希望使用HashSet保证集合中不含有重复的对象,这时需要重写hashCode方法。
HashSet的去重原理是,先比较hashCode,若hashCode唯一则存储,不唯一则再调用equals。
在HashSet中,因为只重写equals()的话,hashCode()依旧是调用Object.hashCode()。由于没有重写hashCode(),那么不同对象的hashCode必然不同。
要求:以下两个对象在HashSet中只存储1个
people people1= new people(“1001”,“张三”);
people people2= new people(“1001”,“张三”);
但重写了equals但没重写hashCode时,结果判断对象相等,但其hashCode却不一致。存进set集合的元素为2个。
如果只希望存储1个,那么必须使值相同的对象必须有相同的hashCode,即重写hashCode。
7、说说你理解的面向对象
答:
以实际生活的案例来举一个例子,比如说洗衣服。
如果是面向过程的话,我们会将这个洗衣服任务拆解成一系列的步骤,每一个步骤就是一个函数。
- 第一步,打开洗衣机;
- 第二步,放衣服和洗衣液;
- 第三步,选择洗衣模式,开始洗衣;
- 第四步,等待洗完,拿出衣服。
如果是面向对象的编程方式,我们会拆分成人和洗衣机两个对象,再分析每一个对象,它需要做哪些事情。
人在其中需要做这三件事:
- 第一件打开洗衣机
- 第二件是放衣服和洗衣液
- 第三件事是洗完衣服后拿出衣服。
洗衣机在其中只需要做一件事情:
- 根据洗衣模式洗衣服。
面向过程
更加注重这个事情的每一个步骤以及顺序。他比较直接高效,需要做什么可以直接开始干。
面向对象
更加注重事情有哪些参与者,需求里面有哪些对象,这些对象各自需要做些什么事情。将其拆解成一个个模块和对象,这样会更易于维护和拓展。
封装:把数据和操作数据的方法隐藏起来,对数据的访问只能通过已定义的接口。封装的意义在于,将内部的实现细节隐藏起来,对外部的调用者来说是透明的,调用者也不用关心它内部是怎么实现的,只需要知道这个方法是干什么的就好。
- 隐藏实现细节,提供公共的访问方式
- 提高了代码的复用性
- 提高安全性
继承:从已有类得到继承信息创建新类的过程。子类继承父类属性(静态特征)和方法(动态特征),继承必须遵循封装当中的控制访问。
- 想要使用这些属性和方法的时候,可以直接去使用父类的,而不需要自己再重新去定义,更大程度的实现代码复用。
- 我们不需要写很多的冗余的代码,把共性的全部抽到父类,可以直接调用,如果需要个性化自定义子类的方法时,去重写父类的方法即可。
多态:允许父类的指针或引用指向子类的对象,而在具体访问时实现方法的动态绑定。(允许相同或不同子类型的对象对同一消息作出不同响应。)(使函数在其父类形参不变的前提下,实参可以选择传入不同形参的子类的对象。)
- 使用不同的实例而执行不同操作
- 便于接口的维护和拓展,可以将某一个子类切换成其他的子类,代码不需要做任何的改变,具有可替换性。
多态存在的必要条件:继承、重写、父类引用指向子类对象。
访问控制权限8、spring常用bean的作用域
答:
singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例。
prototype:原型/多例模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例。
request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效。
session:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效。
globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用PortletContext(上下文域)的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效。
9、hashCode相同对象一定相同吗?
答:
通过将对象的内部地址(也就是物理地址)转换成一个整数,然后将该整数通过hash函数的算法就可以得到hashCode。
hashCode代表对象在hash表中的位置,物理地址说的是对象存放在内存中的地址,hashCode的存在主要是为了查找的快捷性。
如果两个对象的hashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置。
10、MyBatis模糊查询怎么写
答:
在配置文件中使用MySql函数concat()
#{ }是预编译处理,MyBatis在处理#{ }时,它会将sql中的#{ }替换为 ?,然后调用PreparedStatement的set方法来赋值。传入字符串后,会在值两边加上单引号,使用占位符的方式提高效率,可以防止sql注入。
${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中,可能引发sql注入。
11、WEB安全问题,怎么解决
答:
跨域问题可通过在Controller类上添加注解@CrossOrigin解决(SpringMVC 4.2或以上版本)
12、ThreadLocal是什么,使用场景
答:
ThreadLocal是一个本地线程副本变量工具类,主要用于将私有线程和该线程存放的副本对象做一个映射,使各个线程之间的变量互不干扰。(ThreadLocal在每个线程都创建副本,每个线程可以访问自己的副本,线程之间相互不影响。)
多线程环境中为每一个jdbc分配一个Connection连接,使用ThreadLocal去保存连接,这样就保证了每个线程在自己的连接上操作数据库,不会出现A线程关闭B的Connnection操作。
Web中的session管理时,可以使用ThreadLocal记录每个线程的Session,这样保证每个线程都可以获取自己的session
解决线程安全问题,对于需要进行线程隔离的变量,可以使用ThreadLocal存储,确保线程隔离
13、重载和重写的区别
答:
重载是方法名相同,形参列表不同的构造器、方法间彼此构成重载,与权限修饰符、返回值类型无关。
重写是子类在继承父类的基础上进行的,对其非private的方法的方法体进行修改的操作称为方法的重写。
2022-06-08
1、为什么Java 代码可以实现一次编写、到处运行?
答:
Java编译产生的不是针对特定平台的机器码,而是一种与平台无关的字节码文件(即.class文件)。
不同平台上的JVM是不同的,但他们提供给Java字节码程序的接口是完全相同的。
相同的字节码在不同平台上,但通过中间的转换器JVM实现了“一次编译,到处运行”的效果。
2、一个Java文件里可以有多个类吗(不包含内部类)?
答:
可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。一个文件中可以只有非public类,如果只有一个非public类,此类可以跟文件名不同。
3、为啥要有包装类?
答:
基本类型不是类,不能new出来,因此不具备面对对象的功能,无法调用方法。包装类让基本数据类型也具有对象的特征
如我们在使用集合类型Collection时就一定要使用包装类型而非基本类型。(集合只能存放引用类型的数据,不能存放基本数据类型)
在一个类或接口或方法中定义一个泛型的数据类型,当使用这个类、接口、方法时,要把泛型定义成具体的基本数据类型就必须使用基本数据类型对应的包装类进行定义。 (虚拟机在编译时会把带泛型的转换成Object类型,而基本数据类型不属于Object 所以不能装)
4、说一说自动装箱、自动拆箱的应用场景
答:
5、int和Integer有什么区别,二者在做==运算时会得到什么结果?
答:
1、int是java的基本数据类型;Integer是int提供的封装类;
2、int默认值是0;Integer默认是NULL;
3、int直接储存数据;Integer是对象,需要用一个引用指向对象;
4、声明int的变量不需要实例化,而声明Integer的变量需要实例化。
二者在做==运算时会返回false,因为int保存数据,Integer保存地址。
6、说一说对字符串拼接的理解
答:
StringBuilder:不是线程安全的,每次字符串拼接都只是扩展内部byte[]数组,只⽣产⼀个最终的string,所以这种效率最⾼。
- 底层实际上是一个初始化容量16的 byte[]数组
- 字符串拼接调用append()方法,底层将字符串追加到byte[]数组中。
- 如果byte[]数组满了,会自动扩容。
- 具体扩容机制是:尝试扩容为两倍加2,如果还小于所需容量,则直接将所需容量作为实际数组长度。如果大于所需容量,则可以作为实际数组长度。
StringBuffer:与StringBuilder相⽐只是多加了个synchronized,是线程安全的,在单线程的情况下相差不⼤。
StringUtils.join:可以看到其内部还是⽤StringBuilder实现,但是每次循环都多了个分隔符的判断所以慢了⼀点。
concat:每次连接都会⽣成⼀个string,所以效率很低。
+:在java内部是对+进行了重载,在处理String的过程中要创建一个StringBuffer对象,用StringBuffer对象的append方法对字符串进行连接,最后调用toString方法返回String字符串。但是从结果来看效率最低
7、StringBuffer、StringBuild的区别
答:
相同点:
- 都是可变的字符串
不同点:
- StrngBuffer是线程安全:因为StringBuffer 的所有公开方法都是 synchronized 修饰的,而 StringBuilder 并没有 synchronized 修饰。
-
缓冲区:StringBuffer 每次获取 toString 都会直接使用缓存区的 toStringCache 值来构造一个字符串。而 StringBuilder 则每次都需要复制一次字符数组,再构造一个字符串。
- 性能:StringBuffer 是线程安全的,它的所有公开方法都是同步的,StringBuilder 是没有对方法加锁同步的,所以毫无疑问,StringBuilder 的性能要远大于 StringBuffer。
8、在finally 中return会发生什么?
答:
1、finally 语句块在try和catch语句块中的return语句之前执行
2、finally块中的return语句会覆盖try块中的return返回
public static int test4() {
try {
System.out.println(“try代码块”);
return 1;
}catch(Exception e) {
System.out.println(“catch代码块”);
}finally {
System.out.println(“finally代码块”);
return 2;
}
}
分析:此时程序会按照顺序执行。①首先进入到try中,打印"try代码块",但并没有将1返回,只是先将1保存起来;②接着进入到finally中,打印"finally代码块";③再执行return 2,将return 1保存的值覆盖,返回2。
9、说一说你对 MySQL索引的理辉
答:
1、MySQL中的索引之于表就像书本的目录一样,可以极大的提高搜索的速度。
2、索引通常使用在数据量比较大的业务场景。
3、设置为索引的字段不应该或者几何不会进行DML操作,如主键索引。
原理:对数据进行查询操作的时候,数据库会先判断该字段是否是索引,如果是索引,则通过索引找到该条数据的物理地址,再通过物理地址取出该数据内容,底层的原理是B+ 树。
数据查询语言DQL:SELECT <字段名表> FROM <表或视图名> WHERE <查询条件>
数据操纵语言DML:1) 插入:INSERT 2) 更新:UPDATE 3) 删除:DELETE
数据定义语言DDL:用来创建数据库中的各种对象-----表、视图、索引、同义词、聚簇等。
数据控制语言DCL:授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等。
10、只要创建了索引,就一定会走索引吗?
答:问题转换->mysql增加索引,那些情况会失效呢?
1、查询条件在索引列上使用函数操作,或者运算的情况
2、查询条件字符串和数字之间的隐式转换
3、特殊修饰符 %%, Or 将不走索引
4、索引优化器选择最优的索引
索引优化器的存在,就是找到一个索引扫描行数最少的方案去执行语句。扫描行数是根据统计信息来估算的值。这个统计信息就是常说的索引的“区分度”。
explain:查询sql语句的执行计划,查看sql语句有没有使用上索引,有没有全表扫描等。
11、索引是越多越好吗?
答:
1、数据量小的表不需要建立索引,建立会增加额外的索引开销。
2、数据变更需要维护索引,因此更多的索引意味着更多的维护成本。
3、更多的索引意味着也需要更多的空间(索引也是需要空间来存放的)。
12、数据库索引失效了怎么办?
答:
13、请你说说 Spring的核心是什么
答:
IOC称之为控制反转,简单来说就是将对象的创建的权利及对象的生命周期的管理过程交由Spring框架来处理,从此在开发过程中不再需要关注对象的创建和生命周期的管理,而是在需要时由Spring框架提供,这个由spring框架管理对象创建和生命周期的机制称之为控制反转。而在创建对象的过程中Spring可以依据配置对对象的属性进行设置,这个过程之为依赖注入,也即DI。
面向切面编程是一种设计思想。主要由连接点,切入点,增强/通知、切面组成。AOP依托于代理模式进行实现,所以AOP拥有代理模式的特性。可以在不改变原有类的情况下,能动态的添加某些功能。所以说比较适合来实现,打印请求日志,权限校验,等功能。针对不同的场景,AOP可以选择使用JDK动态代理或CGLIB代理来实现。由于CGLIB创建出来的代理类运行速度快于JDK动态代理,但是创建的过程太慢,所以可以将其创建出来的代理类交由IOC容器进行管理,免去了重复创建代理不必要的性能开销,来提高运行速度。
连接点 Joinpoint:是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。(通俗理解:业务层接口的所有方法都叫连接点)
切入点 Pointcut:指我们要对哪些连接点进行拦截的定义。 (通俗理解:被增强的业务层接口的方法叫切入点)。切入点和连接点不是一对一的关系,一个切入点可以匹配多个连接点。
- 切入点表达式:AspectJ 定义了专门的表达式用于指定切入点。
通知/增强 Advice:指拦截到连接点 之后所要做的事情就是通知。
- ①前置通知
- ②后置通知
- ③环绕通知
- ④异常通知
- ⑤最终通知
切面:切入点和通知的结合。 (通俗理解:建立切入点方法和通知方法在执行调用的对应关系就是切面)
JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
- JDK代理使用的是反射机制实现aop的动态代理
- JDK动态代理需被代理类实现接口
CGLIB动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
- CGLIB代理使用字节码处理框架asm,通过修改字节码生成子类
- CGLIB代理通过继承方式实现代理(对于 final 类或方法,是无法继承的)
14、说说你对 Spring Boot的理解
答:
15、 Spring 中默认提供的单例是线程安全的吗?
答:
不是线程安全的。对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。
如果单例Bean是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。(比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。)
有状态就是有数据存储功能
无状态就是不会保存数据
16、Spring 如何管理事务?
答:
17、在java中构造函数与一般函数有什么区别
答:
构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化,只调用一次。
一般函数:对象创建后,需要函数的功能时才调用,可以重复调用。
18、在java序列化期间那些变量未序列化。
答:
静态变量(static修饰)属于类,而不是对象,因为它们不是对象状态的一部分,故在Java序列化过程中不会保存(序列化)它们。
瞬态变量(trasient修饰)可以阻止修饰的字段被序列化到文件中,故也不包含在Java序列化过程中。
在被反序列化后,静态变量和瞬态变量的值被设为初始值,比如int型的值会被设置为 0,对象型初始值会被设置为null。
序列化时把对象改成可以存到磁盘或通过网络发送到其他运行中的Java虚拟机的二进制格式的过程,并且可通过反序列化对象状态。
19、如何在自定义端口上运行spring boot程序。
答:
在application.yml或application.properties配置文件上指定端口号如:server.port=8090
20、简单描述一下spring boot 启动加载过程。
答:
第⼀部分进⾏SpringApplication的初始化模块,配置⼀些基本的环境变量、资源、构造器、监听器;
第⼆部分实现了应⽤具体的启动⽅案,包括启动流程的监听模块、加载配置环境模块、及核⼼的创建上下⽂环境模块;
第三部分是自动化配置模块,该模块作为springboot⾃动配置核⼼。
2022-06-09
1、并行与并发的区别是什么?
答:
并发(concurrency):把任务在不同的时间点交给处理器进行处理。在同一时间点,任务并不会同时运行。
并行(parallelism):把每一个任务分配给每一个处理器独立完成。在同一时间点,任务一定是同时运行。
2、接口与抽象类的区别是什么?
答:
1)抽象类允许包含某些方法的实现,而接口是不允许的。
2) 抽象类中可以有抽象方法,也可以有非抽象方法。
Java8以前接口中包含常量、抽象方法;
Java8接口中包含常量、抽象方法、默认方法、静态方法;
Java9接口中包含常量、抽象方法、默认方法、静态方法、私有方法。
3)抽象类中的成员变量可以实现多个权限 public private protected final等,接口中只能用 public static final修饰。
3、怎样防止死锁?
答:
死锁的产生条件:
互斥条件:进程对所分配到的资源不允许其他进程访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源。
请求和保持条件:进程获得一定的资源后,又对其他资源发出请求,但是该资源可能被其他进程占有,此时请求阻塞,但该进程不会释放自己已经占有的资源。
不可剥夺条件:进程已获得的资源,在未完成使用之前,不可被剥夺或不能被其他进程强行夺走,只能在使用后自己释放。
循环等待条件:进程发生死锁后,必然存在一个进程-资源之间的环形链 ,环路中每个进程都在等待下一个进程所占有的资源。
死锁的处理方法:
鸵鸟策略:因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。
死锁检测与死锁解除:在死锁产生前不采取任何措施,只检测当前系统有没有发生死锁,若有,则采取一些措施解除死锁。
死锁的检测:如果资源分配图中没有环路,则系统没有死锁; ②如果资源分配图中出现了环路,则系统可能有死锁。
死锁的解除:
1、资源剥夺:挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他死锁进程。(但应该防止被挂起的进程长时间得不到资源,而处于资源匮乏的状态。);
2、撤销进程:强制撤销部分、甚至全部死锁进程并剥夺这些进程的资源。(撤销的原则可以按进程优先级和撤销进程代价的高低进行);
3、进程回退:让一个或多个进程回退到足以避免死锁的地步。【进程回退时自愿释放资源而不是被剥夺。要求系统保持进程的历史信息,设置还原点。】
死锁恢复:
1、利用抢占恢复。从一个或多个进程中抢占足够数量的资源分配给死锁进程,以解除死锁状态。
2、利用回滚恢复。周期性地检查进程的状态(包括请求的资源),将其写入一个文件,当发生死锁,回滚到之前的某个时间点
3、通过杀死进程恢复。终止或撤销系统中的一个或多个死锁进程,直至打破死锁状态。
死锁预防:
破坏互斥条件:即允许进程同时访问某些资源。但是,有的资源是不允许被同时访问的,像打印机等等。所以,这种办法并无实用价值。
破坏不可剥夺条件:当一进程占有一独占性资源后又申请一独占性资源而无法满足,则退出原占有的资源。
破坏请求与保持条件:采用资源预先分配策略,即进程运行前申请全部资源,满足则运行,不然就等待,这样就不会占有且申请。
破坏循环等待条件:实行顺序资源分配法
死锁避免:
银行家算法:当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程已占用的资源数与本次申请资源数之和是否超过了该进程对资源的最大需求量。若超过则拒绝分配资源。若没超过则再测试系统现存的资源能否满足该进程尚需的最大资源量,若满足则按当前的申请量分配资源,否则也要推迟分配。
【在动态分配资源的过程中,银行家算法防止系统进入不安全状态,从而避免死锁】
安全序列:是指系统能按某种进程推进顺序(P1, P2, P3, …, Pn),为每个进程 Pi 分配其所需要的资源,直至满足每个进程对资源的最大需求,使每个进程都可以顺序地完成。这种推进顺序就叫安全序列【银行家算法的核心就是找到一个安全序列】。
2022-06-10
1、怎么从线程池中获得可用线程
答:线程池对象.execute(实现了Runnable接口的线程)
为什么要使用线程池?
1)多核处理的好处是,省略的上下文的切换开销。
2)降低资源消耗。通过重复利用已创建的线程,降低线程创建和销毁造成的消耗。
3)提高响应速度。当任务到达时,任务可以不需要等到线程创建就立即执行。
4)提高线程的可管理性。线程是稀缺资源,如果无线创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
2、Java集合
答:Java 集合可分为Collection和 Map 两种体系。
-
Collection接口:单列数据,定义了存取一组对象的方法的集合
-
-
List:元素有序(指的是存储时,与存放顺序保持一致)、可重复的集合
-
ArrayList:底层结果是数组,所以查询快,增删慢,线程不安全。
1、在ArrayList
集合的底层是由一个可变的动态Object[]
数组组成的,由于他是由数组构成的,所以该集合类框架对于随机访问的效率很高,时间复杂度为O(1)
。
2、插入元素的时候,如果采用默认的add(E e)
便会在数组的末端插入,时间复杂度近似为O(1)
。
3、如果在数组中间插入一个元素,那么他会先将该位置后面的元素整体往后移动一位后,再把待插入元素插入,这时的时间复杂度就近似为 O(n)。
4、所有的方法均没有进行线程安全方面的设计,故可见他是一个线程不安全的集合。
5、ArrayList的数组是在第一次添加元素的时候将数组设置为默认的初始化大小(10)的,是一种懒加载方式。
6、在ArrayList
中,其扩容的方法主要为grow()
方法:数组扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量增长大约是其容量的1.5倍。
7、扩容时,新计算的扩容大小小于数组最小大小,则以默认初始长度10为实际扩容大小;新计算的扩容大小大于数组最小大小且小于数组最大大小,则以是以近乎于原数组大小的1.5倍扩容;新计算的扩容大小大于数组最大大小,则以Integer的最大长度为实际扩容大小; -
LinkedList:底层结果是双向链表,查询慢,增删快,线程不安全。
1、因为在链表这种数据结构中查询一个元素,必须从头结点开始一次遍历,并且他在内存空间中是一种内存地址不连续的存储方式,寻址代价比较大,如果链表比较长,那么查询效率就会比较低,采用双向链表,有两个首位节点,可以从两个方向开始遍历链表,在查询遍历的时候,一定程度上可以提高一定的效率。
2、链表没有扩容机制,直接在前面和后面新增(链表的头插法和尾插法) -
Vector:底层结果是数组,查询快,增删慢,线程安全。
1、和 ArrayList的底层数据结构一样,都是利用一个可变大小的动态 Objec[]数组来存储数据结构,初始化大小为10。
2、扩容机制和 ArrayList类似,只是新的大小计算方式不同。在原来的数组大小的基础上加上扩容量,默认值为0
故在没有给定自定义扩容量或者扩容量给定为0时,默认扩容到原来的 2 倍。
-
-
Set:元素无序、不可重复的集合
-
HashSet:无序,唯一,线程不安全,允许null值。
1、HashSet其实是HashMap的一个实例,都是一个存放链表的数组,允许有null元素,HashSet中的元素都存放在HashMap中的key上面,value是一个固定Object对象, -
LinkedHashSet:有序、LinkedHashSet底层使用LinkedHashMap来保存所有元素,它继承与HashSet,其所有的方法操作上又与HashSet相同。
1、维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序。 -
TreeSet:是一个有序集合,是基于TreeMap实现的支持两种排序方式,自然排序和定制排序,TreeSet是非同步的,线程不安全。
-
-
-
Map接口:双列数据,保存具有映射关系“key-value对”的集合
-
-
HashMap:无序、线程不安全、不允许键值重复、允许null值和null键。初始化大小16
1、底层结构是哈希表,不过在jdk1.8以前,哈希表是由数组+链表合体实现的;在jdk1.8中,哈希表是由数组+链表+红黑树合体实现的;当链表长度超过阈值(8)时,会自动转为红黑树,这样就大大的提高了效率,减少了查询时间。
2、当我们往HashMap中put元素时,利用key的hashCode重新hash计算出当前对象的元素在数组中的下标。如果出现hash值相同的key,若key相同,则覆盖原始值。如果key不同(出现冲突),则将当前的key-value放入链表中。jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)。 -
添加元素的过程
resize:原数组中的数据必须重新计算其在新数组中的位置,并放进去。
-
LinkedHashMap:LinkedHashMap继承于HashMap,底层使用哈希表和双向链表来保存所有元素,此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序。并且它是非线程安全,允许使用null值和null键。
1、LinkedHashMap中可以保持两种顺序,分别是插入顺序和访问顺序,这个是可以在LinkedHashMap的初始化方法中进行指定的。相对于访问顺序,按照插入顺序进行编排被使用到的场景更多一些,所以默认是按照插入顺序进行编排。 -
TreeMap:是一个有序(默认按键的升序)集合,底层是红黑树,每个key-value都作为一个红黑树的节点。不允许null键和null值、线程不安全。
-
Hashtable:底层结果与HashMap相同,无序,唯一不同的就是线程安全,键和值都不允许为null,:默认初始容量为11,提供了对键的列举。
1、Hashtable底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。
2、synchronized是针对整张Hash表的,即每次锁住整张表让线程独占
-
3、怎么理解SpringBoot和SpringCloud
答:
4、Linux常用命令
答:
- 目录操作命令
- 文件操作命令
- 压缩与解压命令
- 文件权限命令
- 其他命令
5、分布式下服务怎么保持一致性
答:
使用分布式锁,如:
用户微服务下单成功后,往第三方redis存一个标识位,证明下单开始了。
跳到另一个微服务,如库存微服务,数量--,当库存微服务成功后,去第三方redis中存标识位。
当整个流程完成后,比较所有的标识位,若都为成功标识位,则流程结束;否则回滚。
6、传统服务与微服务有什么区别
答:
传统服务
优点:
单体架构的优点在于⽅便管理,所有代码在同⼀项⽬中,但是当需求越来越多,项⽬规模越来越⼤,其坏处也很明显。
缺点:
1、项⽬过于臃肿,部署效率低下
2、开发成本⾼
3、⽆法灵活拓展
微服务
服务拆分粒度更细:微服务可以说是更细维度的服务化,⼩到⼀个⼦模块,只要该模块依赖的资源与其他模块都没有关系,那么就可以拆分为⼀个微服务。
服务独立部署:传统的单体架构是以整个系统为单位进⾏部署,⽽微服务则是以每⼀个独⽴组件为单位进⾏部署。
服务独立维护:将每个微服务都隔离为独⽴的运⾏单元之后,任何⼀个或者多个微服务的失败都将只影响⾃⼰或者少量其他微服务,⽽不会⼤⾯积地波及整个服务运⾏体系。可以隔离故障,避免服务整体down掉风险。
扩展不同:微服务更容易按需求进行横向和纵向扩展。
7、SpringCloud的注册中心是依赖于Zookeeper吗?
答:不是,可以根据需要选择Eureka、Zookeeper等注册中心
CPA原则
:指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容忍性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
分区的情况下,各节点如果无法相互进行网络通信,那就只能在一致性和可用性中选取其一:
如果选择在连接不到别的节点时不对外提供服务,就保证了一致性抛弃了可用性;
如果选择在连接不到别的节点时依然对外提供服务,就保证了可用性抛弃了一致性;
所以如果既想保证可用性又想保证一致性,那就只能避免分区,即抛弃了分区容忍性。
Zookeeper的选择
从概念上来说,ZooKeeper它所做的就是确保对数据的修改都会被复制到集合体中超过半数的节点上。如果少于半数的机器出现故障,则最少有一台机器会保存最新的状态,那么这台机器就是我们的Leader。其余的副本最终也会更新到这个状态。如果 Leader挂了,由于其他机器保存了Leader的副本,那就可以从中选出一台机器作为新的Leader继续提供服务。
从原则上来说,zookeeper保证了强一致性,但实际上写操作的2pc提交不需要所有的节点都投票通过,而是超过半数的节点投票通过即可,那么有的节点有可能没有第一时间接收到写操作的同步而leader已经通过该写操作,这样的话连接到该节点的服务只能说得到了数据单调一致性的保障,而不是强一致性的保障。但是总的来说,zookeeper是相当偏向于一致性而非可用性的服务注册与管理中间件,需要注意的是这也会大幅度增加写入数据的性能成本,但是一般情况下作为服务中心写入的数据并不多,还在可接受的范围内。
Eureka的选择
相对于zookeeper,eureka相当偏向于A而非C,即是说一台连接不到集群的eureka节点依然可以对外提供服务,即使提供的数据不一定是最新的,但是在某些情况下总比服务之间宕机要好。
在eureka集群中,如果某个节点发生宕机,eureka不会有类似zookeeper选举的行为,即不会对外停止服务。客户端请求会切换到别的eureka节点,当宕机的服务器重新恢复后会被再次加入集群管理中同步别的eureka server保存的注册信息。当网络分割故障发生时,每个eureka server节点都能继续对外提供服务。
eureka server还有心跳机制,默认情况下eureka server一段时间内没有接受服务提供者发送的心跳就会将其剔除,但是也有可能是eureka server发生了网络分区故障。如果eureka server在一段时间内丢失了大量心跳,那么会进入自我保护模式,此时有以下行为模式:
1、Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
2、Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用。
3、当网络稳定时,当前Eureka Server新的注册信息会被同步到其它节点中。
因此Eureka Server可以很好的应对因网络故障导致部分节点失联的情况,而不会像ZK那样如果有一半不可用的情况会导致整个集群不可用而变成瘫痪
总结:
什么时候采用什么中间件呢,可能要根据具体业务分析。如果是支付相关,无法容忍注册服务列表的不一致,那么就要使用更加能保证一致性的zookeeper,如果是推送新闻等服务,短暂的不一致比起服务宕机影响更小。
2022-06-13
1、Java反射的作用
答:
什么是反射?
反射是Java的特征之一,是一种间接操作目标对象的机制。
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
反射的作用
通过反射可以使程序代码访问装载到JVM 中的类的内部信息
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
- 生成动态代理
反射的应用场景
- 逆向代码 ,例如反编译
- 与注解相结合的框架,例如 Retrofit
- 单纯的反射机制应用框架,例如 EventBus
- 动态生成类框架 例如Gson
反射的缺点
-
性能问题
使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此Java反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。 -
使用反射会模糊程序内部逻辑
程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。
2、写出Throwable与RunTimeException之间的关系以及使用场景
答:
Throwable包括:
-
Error类:
- 属于系统级错误称之为“错误”,不可被捕获
- Error无需在程序中以throws子句中抛出
- 存在Error错误程序不能运行或是运行中断
-
Exception类:
- 属于应用程序级错误称之为“异常”,可以通过捕获避免
- Exception需要抛出
- 存在Exception错误程序可运行并抛出
RuntimeException那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。可能在执行方法期间抛出但未被捕获的 RuntimeException 的任何子类都无需在 throws 子句中进行声明。
RuntimeException父类是Exception
几种常见的RuntimeException:
- 算术异常类:ArithmeticExecption
- 空指针异常类:NullPointerException
- 类型强制转换异常:ClassCastException
- 数组负下标异常:NegativeArrayException
- 数组下标越界异常:ArrayIndexOutOfBoundsException
- 违背安全原则异常:SecturityException
- 文件已结束异常:EOFException
- 文件未找到异常:FileNotFoundException
- 字符串转换为数字异常:NumberFormatException
- 操作数据库异常:SQLException
- 输入输出异常:IOException
- 方法未找到异常:NoSuchMethodException
3、(前端)margin与padding的区别
答:
4、(前端)简述dix与span的区别,什么changing上需要把span转为行内块元素
答:
5、(前端)简述let与var的区别
答:
6、(前端)vue中refs分别有什么用途
答:
7、(前端)vue中<input:value=“abc”/>与<input value=“abc"/>
答:
8、JRE、JDK、JVM的区别
答:
JDK(Java Development Kit Java开发工具包),JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE。所以安装了JDK,就不用在单独安装JRE了。其中的开发工具包括编译工具(javac.exe) 打包工具(jar.exe)等。
JRE(Java Runtime Environment Java运行环境) 是 JDK 的子集,也就是包括JRE 所有内容,以及开发应用程序所需的编译器和调试器等工具。JRE 提供了库、Java 虚拟机(JVM)和其他组件,用于运行 Java 编程语言、小程序、应用程序。
JVM(Java Virtual Machine Java虚拟机),JVM可以理解为是一个虚拟出来的计算机,具备着计算机的基本运算方式,它主要负责把 Java 程序生成的字节码文件,解释成具体系统平台上的机器指令,让其在各个平台运行。
9、sleep与wait的区别
答:
sleep
- 属于Thread的方法
- sleep方法没有释放锁
- sleep可以在任何地方使用
wait
- 属于Object的方法
- wait方法释放了锁,使得其他线程可以使用同步控制块或方法
- wait、notify和notifyAll只能在同步控制方法或同步控制块里面使用
10、JVM的垃圾回收机制
答:
2022-06-14
1、&和&&的区别
答:
&:[条件1 & 条件2],不论条件1成不成立,继续执行条件2
&&:[条件1 && 条件2],如果条件1成不成立,则条件2不执行
2、数据连接池的工作机制是什么?常用开源连接池有哪些?
答:
应用程序直接获取数据库连接:
用户每次请求都需要向数据库获取链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间较长。如果网站一天10万访问量,数据库服务器需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、脱机。如下图所示
应用程序直接获取数据库连接使用数据库连接池优化程序性能:
数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中提现的尤为突出,对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对整个问题提出来的。数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。如下图所示:
使用数据库连接池获取数据库连接数据库连接池的工作机制:
- 服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。
- 客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其表记为忙。
- 如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量由配置参数决定。
- 当使用的池连接调用完成后,池驱动程序将此连接表记为空闲,其他调用就可以使用这个连接。
常见的数据库连接池:
-
C3P0:是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。
-
Proxool:是一个Java SQL Driver驱动程序,提供了对选择的其它类型的驱动程序的连接池封装。可以非常简单的移植到现存的代码中,完全可配置,快速、成熟、健壮。可以透明地为现存的JDBC驱动程序增加连接池功能。
-
Jakarta DBCP:DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池。DBCP可以直接的在应用程序中使用。
-
DDConnectionBroker:是一个简单、轻量级的数据库连接池。
-
DBPool:是一个高效、易配置的数据库连接池。它除了支持连接池应有的功能之外,还包括了一个对象池,使用户能够开发一个满足自己需求的数据库连接池。
-
XAPool:是一个XA数据库连接池。它实现了javax.sql.XADataSource并提供了连接池工具。
-
Primrose:是一个Java开发的数据库连接池。当前支持的容器包括Tomcat4&5、Resin3与JBoss3。它同样也有一个独立的版本,可以在应用程序中使用而不必运行在容器中。Primrose通过一个WEB接口来控制SQL处理的追踪、配置,以及动态池管理。在重负荷的情况下可进行连接请求队列处理。
-
SmartPool:是一个连接池组件,它模仿应用服务器对象池的特性。SmartPool能够解决一些临界问题如连接泄漏(connection leaks)、连接阻塞、打开的JDBC对象(如Statements、PreparedStatements)等。
-
MiniConnectionPoolManager:是一个轻量级JDBC数据库连接池。它只需要Java1.5(或更高)并且没有依赖第三方包。
-
BoneCP:是一个快速、开源的数据库连接池。帮用户管理数据连接,让应用程序能更快速地访问数据库。比C3P0/DBCP连接池速度快25倍。
-
Druid:Druid不仅是一个数据库连接池,还包含一个ProxyDriver、一系列内置的JDBC组件库、一个SQL Parser。
3、多线程有几种实现方法?同步有几种实现方法?
答:
多线程的实现方法:
-
继承Thread
-
实现Runnable接⼝
共同点:
不论⽤哪种⽅法,都必须⽤Thread(如果是Thead⼦类就⽤它本⾝)产⽣线程,然后再调⽤start()⽅法。
不同点:
1、继承Thread类有⼀个缺点就是单继承,⽽实现Runnable接⼝则弥补了它的缺点,可以实现多继承。
2、继承Thread类,必须产⽣多个Runnable实例对象,然后再⽤Thread产⽣多个线程;⽽实现Runnable接⼝,只需要建⽴⼀个实现这个类的实例,然后⽤这⼀个实例对象产⽣多个线程。即实现了资源的共享性。
同步的实现方法:
-
synchronized
-
wait与notify
wait():使一个线程处于等待状态,并且释放所持有的对象的lock。
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。
2022-06-16
1、redis的五种数据类型,穿透、击穿、雪崩分别是什么?
答:
Redis 自身是一个 Map,其中所有的数据都是采用 key : value 的形式存储 ,数据类型指的是存储的数据的类型,也就是 value 部分的类型,key 部分永远都是字符串
string(字符串):
hash(哈希):底层使用哈希表结构实现数据存储。hash类型下的value只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。
list(列表):允许用户从序列的两端推入或者弹出元素,列表由多个字符串值组成的有序可重复的序列,是链表结构。
set(集合):与hash存储结构完全相同,仅存键,不存值(nil)。是键为string类型元素的不重复的无序组合。
sort set (有序集合):在set的存储结构基础上添加可排序字段(score)。不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。value是唯一的,但分数字段(score)却可以重复。
2、inner join 和 leftjoin的区别
答:
inner join:只返回两个表中联结字段相等的行
(inner join的数量小于等于左表和右表中的记录数量)
left join:返回包括左表中的所有记录和右表中联结字段相等的记录。
(left join的数量以左表中的记录数量相同)
right join:返回包括右表中的所有记录和左表中联结字段相等的记录。
(right join的数量以右表中的记录数量相同)
穿透:
击穿:
雪崩:
3、synchroined 和lock的区别
答:
-
synchroined :可以加在方法上,也可以加在特定代码块中
- 普通同步方法,锁是当前实例对象
- 静态同步方法,锁是当前类的class对象
- 同步方法块,锁是括号里面的对象
-
lock :只能加在特定代码块中
- 在加锁和解锁处需要通过lock()和unlock()显示指出。
(以上为部分区别,更多详情未记录)
4、spring什么情况下事务失效
答:
问题剖析->Spring事务的原理是AOP,进⾏了切⾯增强,那么失效的根本原因是->AOP不起作⽤了
常见情况有如下⼏种
1、发⽣⾃调⽤
类⾥⾯使⽤this调⽤本类的⽅法(this通常省略),此时这个this对象不是代理类,⽽是 UserService对象本⾝。
解决⽅法->让那个this变成UserService的代理类即可。
2、⽅法不是public的
@Transactional 只能⽤于public 的⽅法上,否则事务不会失效。原理在于Spring的事务管理依靠的动态代理模式,当在同一个类中调用一个非事务方法,是不会生成代理对象的,自然也不会触发事务。
解决⽅法->如果要⽤在⾮public ⽅法上,可以开启 Aspectj 代理模式。
3、数据库不⽀持事务
4、没有被spring管理
5、异常被吃掉,事务不会回滚(或者抛出的异常没有被定义,默认为RuntimeException)
5、字符串的创建
答:
- 例1
String s1="1";
s1="2";
结论:生成2个字符串,"1"、"2"。
- 例2
String s1 = "10" + "1";
结论:生成3个字符串,"10"、"1"、"101"。
- 例3
String s1 = new String("abc");
结论:生成2个字符串,一个"abc"存储在常量池,另一个"abc"存储在堆内存;s1保存着堆内存中"abc"的引用。
- 例4
String s1 = "10";
s1 += "1"; // s1=s1+"1";
结论:生成3个字符串,"10"、"1"存储在常量池,"101"存储在堆内存,s1保存着堆内存中"101"的引用。
注意:任何与变量相加的字符串都会产生一个新字符串,存储在堆内存。
- 例5
String str1 = "ab"+"cd";
String str2 = new String("ab")+new String("cd");
结论:
第一句:在编译时已经将"ab"+"cd"换成"abcd"所以和String str1 = “abcd”;
是一模一样的;
第二句:会在常量池中创建ab、cd并在堆上存储ab和cd在常量池的引用, 在栈上创建引用变量str2 ,而str2 引用的对象实体是"abcd",因此会在堆上创建"abcd",同时把"abcd"的地址复制给str2 ;
2022-06-17
1、Git的分支规划和使用规范
答:
① Production/Master 分支
这个分支最近发布到生产环境的代码,最近发布的Release, 这个分支只能从其他分支合并,不能在这个分支直接修改。
② Develop 分支
这个分支是我们是我们的主开发分支,包含所有要发布到下一个 Release 的代码,这个主要合并与其他分支,比如 Feature 分支。
③ Feature 分支
这个分支主要是用来开发一个新的功能,一旦开发完成,我们合并回 Develop 分支进入下一个Release。
④ Release分支
当你需要一个发布一个新 Release 的时候,我们基于 Develop 分支创建一个 Release 分支,完成 Release 后,我们合并到 Master 和 Develop 分支。(为新产品的发布做准备)
⑤ Hotfix分支
当我们在 Production(生产环境) 发现新的 Bug 时候,我们需要创建一个 Hotfix, 完成 Hotfix 后,我们合并回 Master 和 Develop 分支,所以 Hotfix 的改动会进入下一个 Release。
2、Maven的作用以及优缺点
答:
优点如下:
①简化了项目依赖管理:
②易于上手,对于新手可能一个"mvn clean package"命令就可能满足他的工作
③便于与持续集成工具(jenkins)整合
④便于项目升级,无论是项目本身升级还是项目使用的依赖升级。
有助于多模块项目的开发,一个模块开发好后,发布到仓库,依赖该模块时可以直接从仓库更新,而不用自己去编译。
⑤maven有很多插件,便于功能扩展,比如生产站点,自动发布版本等
缺点如下:
①maven是一个庞大的构建系统,学习难度大
②maven采用约定优于配置的策略(convention over configuration),虽然上手容易,但是一旦出了问题,难于调试。
③中国的网络环境差,很多repository无法访问,比如google code, jboss 仓库无法访问等。
3、常见的设计模式及其使用场景
答:
- slf4j: 门面模式
- restTemplate : 模版方法模式
- ribbon : 负载均衡(策略模式)
- IOC: 单例模式 (饿汉,懒汉,登记) ok
- ***Adapter: 适配器模式
- ***pool: 享元模式 思想
- aop: 代理模式(正向反向)
- interceptor: 责任链模式
4、SpringBoot项目中,修改了文件如何重新加载而无需重启服务
答:
Spring Boot 有一个开发工具(DevTools)模块,它能将文件更改自动部署到服务器并自动重启服务器,开发人员可以重新加载 Spring Boot 上的更改,而无需重新启动服务器。
5、请写一个将UTC时间转换成北京时间的方法及单元测试
答:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Created by LiChao on 2017/11/23
*/
public class RegexTest {
public static void main(String args[]) throws ParseException {
UTCToCST("2017-11-27T03:16:03.944Z", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
}
public static void UTCToCST(String UTCStr, String format) throws ParseException {
Date date = null;
SimpleDateFormat sdf = new SimpleDateFormat(format);
date = sdf.parse(UTCStr);
System.out.println("UTC时间: " + date);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) + 8);
//calendar.getTime() 返回的是Date类型,也可以使用calendar.getTimeInMillis()获取时间戳
System.out.println("北京时间: " + calendar.getTime());
}
}
6、如何遍历集合
答:
①循环:
②迭代:
List迭代器 Set迭代器 Map迭代器
③:增强For循环
④:Lambda+增强For循环
7、在SpringBoot项目中,请写一个类实现在执行所有Controoler之前,拦截入参并输出到控制台。
答:
使用Filter拦截器
8、在SpringBoot项目中,请写一个方法实现读取resources目录下的book.txt的内容到List<String>
答:
2022-06-21
1、dao接口能不能方法重载
答:
2、mq发短信 、发邮件 ,不用简单模式 ,怎么发,会不会造成多发重发的情况。
答:
3、mysql删除数据的三种方式。
答:
delete:DELETE from TABLE_NAME where xxx
- DELETE属于数据库DML操作语言,只删除数据不删除表结构,会走事务,执行时会触发trigger.
- 在InnoDB中,DELETE其实并不会真的把数据删除,mysql实际上只是给删除的数据打了个标记为已删除,因此delete删除表中的数据时,表文件在磁盘上所占空间不会变小,存储空间不会被释放,只是把删除的数据行设置为不可见。虽然未释放磁盘空间,但是下次插入数据的时候,仍然可以重用这部分空间(重用 -> 覆盖)。
- DELETE执行时,会先将所删除数据缓存到rollback segement中,事务commit之后生效;
- delete from table_name删除表的全部数据,对于MyISAM会立刻释放磁盘空间,InnoDB不会释放磁盘空间;
- 对于delete from table_name where xxx 带条件的删除,不管是InnoDB还是MyISAM都不会释放磁盘空间;
truncate:Truncate table TABLE_NAME
- 属于数据库DDL定义语言,不走事务,原数据不放到rollback segment中,操作不触发trigger。执行后立即生效,无法找回。
- truncate能够快速清空一个表,并且重置auto_increment的值。delete操作是一行一行执行删除的。
- 立刻释放磁盘空间,不管是InnoDB还是MyISAM。
drop:Drop table Tablename
- 属于数据库DDL定义语言,执行后立即生效,无法找回。
- 立刻释放磁盘空间,不管是InnoDB还是MyISAM
2022-06-23
1、对象序列化的含义,有哪几种序列化,序列化存在的意义
答:
2、同步、异步、并发有何异同,在什么情况下分别使用?使用时应注意什么?
答:
3、java垃圾回收器的基本原理是什么?如何主动通知虚拟机进行垃圾回收?
答:
网友评论