【Java面试整理】(难度系数较高)(18)

1.你的项目使用了 SpringBoot,能讲一下它的优点吗?

学习成本降低;
去除大量的XML配置;
集成了Tomcat,部署很容易;
简化了监控过程
开箱即用。

2.你刚才提到了SpringBoot是开箱即用的,那请问它是怎么做到的?
(https://blog.csdn.net/CoderTnT/article/details/81027391)

3.springMVC的@RequestMapping注解放在方法上和类上分别是什么作用?

4.SpringMVC接受和返回json数据?

5.讲一下SpringMVC的运行流程(https://www.cnblogs.com/xiaoxi/p/6164383.html)

6.能说下IOC和AOP吗(我讲了IOC底层其实就是HashMap,存储的beanId与bean实例的键值对映射关系,归根结底就是反射,工厂和xml解析。面试官非常满意,说这是他见过的最好答案,之后连aop都没让我解释,整个spring直接过关)

7.幂等性、冲正(ticket)

8.面向接口开发编程

9.Js能否操作本地文件(不能,即使js调用windows窗口,也需要用户主动去调用,如果用户没有点击或者使用enter键,那么即使弹出窗口也会被浏览器拦截,被认为这是高危操作)

10.Redis事务(https://blog.csdn.net/wgh1015398431/article/details/53156027)

11.乐观锁,悲观锁

12.Integer缓存

13.内存泄漏和溢出

14.Js闭包(闭包就是能够读取其他函数内部变量的函数。)

15.分布式事务(https://www.cnblogs.com/LBSer/p/4715395.html)

16.ConcurrentHashMap(16个segment)与HashMap

17.存储过程(https://blog.csdn.net/anLA_/article/details/76794442?locationNum=7&fps=1)

18.数据库建立的索引(二叉树,红黑树,B-、B+)和solr索引(正排索引和倒排索引)的区别。

https://www.sohu.com/a/201923614_466939
https://www.sohu.com/a/154640931_478315
https://www.sohu.com/a/156886901_479559
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
https://www.cnblogs.com/Onlywjy/p/8372452.html

19.MySQL函数(https://www.cnblogs.com/slowlyslowly/p/8649430.html)

20.项目中使用过多线程么

21.try、catch、finally都有return时,执行哪个

情况1:try{} catch(){}finally{} return;
        显然程序按顺序执行。
情况2:try{ return; }catch(){} finally{} return;
      程序执行try块中return之前(包括return语句中的表达式运算)代码;
     再执行finally块,最后执行try中return;
     finally块之后的语句return,因为程序在try中已经return所以不再执行。
情况3:try{ } catch(){return;} finally{} return;
     程序先执行try,如果遇到异常执行catch块,
     有异常:则执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码,最后执行catch块中return. finally之后也就是4处的代码不再执行。
     无异常:执行完try再finally再return.
情况4:try{ return; }catch(){} finally{return;}
      程序执行try块中return之前(包括return语句中的表达式运算)代码;
      再执行finally块,因为finally块中有return所以提前退出。
情况5:try{} catch(){return;}finally{return;}
      程序执行catch块中return之前(包括return语句中的表达式运算)代码;
      再执行finally块,因为finally块中有return所以提前退出。
情况6:try{ return;}catch(){return;} finally{return;}
      程序执行try块中return之前(包括return语句中的表达式运算)代码;
      有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;
              则再执行finally块,因为finally块中有return所以提前退出。
      无异常:则再执行finally块,因为finally块中有return所以提前退出。

22.分布式锁(分布式环境怎么保证线程安全)

使用zookeeper实现分布式锁的算法流程,假设锁空间的根节点为/lock:
客户端连接zookeeper,并在/lock下创建临时的且有序的子节点,第一个客户端对应的子节点为/lock/lock-0000000000,第二个为/lock/lock-0000000001,以此类推。
客户端获取/lock下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则监听/lock的子节点变更消息,获得子节点变更通知后重复此步骤直至获得锁;
执行业务代码;
完成业务流程后,删除对应的子节点释放锁。

23.分布式session存储方案

1.粘性session
粘性session是指Ngnix每次都将同一用户的所有请求转发至同一台服务器上,即将用户与服务器绑定。
2.服务器session复制
即每次session发生变化时,创建或者修改,就广播给所有集群中的服务器,使所有的服务器上的session相同。
3.session共享
缓存session,使用redis, memcached。
4.session持久化
将session存储至数据库中,像操作数据一样操作session。

24.强弱软虚引用

强引用(StrongReference)
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
软引用(SoftReference)
如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
弱引用(WeakReference)
弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
虚引用(PhantomReference)
"虚引用"顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。

25.JVM内存模型

1、程序计数器(Program Counter Register)
    程序计数器就是记录当前线程执行程序的位置,改变计数器的值来确定执行的下一条指令。
    Java虚拟机多线程是通过线程轮流切换并分配处理器执行时间的方式实现的。为了线程切换能恢复到正确的位置,每条线程都需要一个独立的程序计数器,所以它是线程私有的。

2、java虚拟机栈(VM Stack)
    java虚拟机栈是线程私有,生命周期与线程相同。创建线程的时候就会创建一个java虚拟机栈。
    虚拟机执行java程序的时候,每个方法都会创建一个栈帧,栈帧存放在java虚拟机栈中,通过压栈出栈的方式进行方法调用。
    栈帧又分为一下几个区域:局部变量表、操作数栈、动态连接、方法出口等。
平时我们所说的变量存在栈中,这句话说的不太严谨,应该说局部变量存放在java虚拟机栈的局部变量表中。
    java的8中基本类型的局部变量的值存放在虚拟机栈的局部变量表中,如果是引用型的变量,则只存储对象的引用地址。

3、本地方法栈(Native Method Stack)
    本地方法栈 为虚拟机使用到本地方法服务(native)。本地方法栈为线程私有,功能和虚拟机栈非常类似。线程在调用本地方法时,来存储本地方法的局部变量表,本地方法的操作数栈等等信息。

4、堆(Heap):
    堆是被所有线程共享的区域,实在虚拟机启动时创建的。堆里面存放的都是对象的实例(new 出来的对象都存在堆中)。
    我们平常所说的垃圾回收,主要回收的就是堆区。为了提升垃圾回收的性能,又把堆分成两块区新生代(young)和年老代(old),更细一点划分新生代又可划分为Eden区和2个Survivor区(From Survivor和To Survivor)。
Eden:新创建的对象存放在Eden区
From Survivor和To Survivor:保存新生代gc后还存活的对象。(使用复制算法,导致有一个Survivor空间浪费)Hotspot虚拟机新生代Eden和Survivor的大小比值为4:1,因为有两个Survivor,所以Eden:From Survivor:To Survivor比值为8:1:1。
老年代:对象存活时间比较长(经过多次新生代的垃圾收集,默认是15次)的对象则进入老年的。
当堆中分配的对象实例过多,且大部分对象都在使用,就会报内存溢出异常(OutOfMemoneyError)。

5、方法区
    方法区是被所有线程共享区域,用于存放已被虚拟机加载的类信息,常量,静态变量等数据。被Java虚拟机描述为堆的一个逻辑部分。习惯是也叫它永久代(permanment generation)
    永久代也会垃圾回收,主要针对常量池回收,类型卸载(比如反射生成大量的临时使用的Class等信息)。
    常量池用于存放编译期生成的各种字节码和符号引用,常量池具有一定的动态性,里面可以存放编译期生成的常量;运行期间的常量也可以添加进入常量池中,比如string的intern()方法。
    当方法区满时,无法在分配空间,就会抛出内存溢出的异常(OutOfMemoneyError)。
    java8中已经没有方法区了,取而代之的是元空间(Metaspace)
26.能不能自己写一个类,叫java.lang.String

27.SQL优化

1、查询优化
保证不查询多余的列与行(不要查没用的字段)
慎用distinct关键字(当数据量大的时候效率会降低)
判断表中是否存在数据
select count(*) from product
select top(1) id from product
选择合适的连接(内连接,左右连接)
2、插入优化
批量插入效率 > 循环插入
同理,修改和删除也尽量批量修改,不可逐个循环修改,例如:(delete product where id<1000)。

28.SQL关键字执行顺序

(8)SELECT(9)DISTINCT <select_list>
(1)FROM <left_table>
(3)<join_type> JOIN <right_table>
(2)ON <join_condition>
(4)WHERE <where_condition>
(5)GROUP BY <grout_by_list>
(6)WITH {CUTE|ROLLUP}
(7)HAVING <having_condition>
(10)ORDER BY <order_by_list>
(11)LIMIT <limit_number>

29.数据库约束

数据库中的五大约束包括:
1.主键约束(Primay Key Coustraint) 唯一性,非空性;
2.唯一约束 (Unique Counstraint)唯一性,可以空,但只能有一个;
3.默认约束 (Default Counstraint) 该数据的默认值;
4.外键约束 (Foreign Key Counstraint) 需要建立两表间的关系;
5.非空约束(Not Null Counstraint):设置非空约束,该字段不能为空。

30.有哪几种索引

31.HashMap底层原理

32.索引啥时候创建,啥时候不创建

主键自动建立唯一索引;
频繁作为查询条件的字段创建索引;
频繁更新的字段不适合创建索引,因为每次更新不单单是更新记录,还会更新索引,保存索引文件;
where条件里用不到的字段,不创建索引;
高并发的情况下一般选择复合索引;
查询中排序的字段创建索引将大大提高排序的速度(索引就是排序加快速查找);
表记录太少,不需要创建索引;
经常增删改的表不适合简历索引;
数据重复且分布平均的字段,因此为经常查询的和经常排序的字段建立索引。注意某些数据包含大量重复数据,因此他建立索引就没有太大的效果,例如性别字段,只有男女,不适合建立索引。

33.MySQL数据库安全

1、修改端口号,2、设置权限,3、禁止远程登录,4、备份,

34.dubbo优化

1、根据实际情况设置多个连接
2、服务和消费最好在同一个局域网
3、整体环境优化(CPU、内存、网络等)
4、项目拆分不可过多,拆分过多,连接过多,会导致带宽不够
5、请求数据要限制大小(默认为8M)
6、超时时间合理使用,比如对客户时间不可设置过长,对服务时间可以设置长一点。

35.ActiveMQ的底层原理
https://blog.csdn.net/qq_22251517/article/details/78035610

36.ajax跨域、cookie跨域(jsonp和cors)

不同域名是无法共享浏览器端本地信息,包括cookies,这即是跨域问题。
简单说一下SSO单点登录的技术实现机制:
1、需要一个统一处理用户登录的单点系统UserCenter。该系统集中处理用户信息,包括用户信息加密存储,用户注册,用户登录验证,SSO接入等;
2、需要接入SSO单点登录的系统(例如业务系统A)不处理任何用户登录信息,服务器端在用户第一次提交请求时,跳转到SSO系统验证是否登陆,如未登录,则一般重定向SSO系统的登录页面,用户登录成功以后,再回跳到业务系统A原来的页面,业务系统A与此同时写入由SSO带回来的用户信息到session中,后续的交互过程中,业务系统A就一直保持有用户的登录信息了。
3、假如用户由上述登录过的业务系统A跳转访问到同样接入到SSO单点登录系统UserCenter的业务系统B,此时业务系统B没有用户登录信息,同样会跳转SSO单点登录系统验证是否登录,SSO检测到用户之前已登录,又重定向到业务系统B,此时系统B从SSO带回登录信息并写入到session,这样用户就做到了,一处登录多处保持登录信息,即完成了SSO单点登录。
需要特别说明的是:在这个SSO单点登录过程中,上述SSO系统UserCenter、业务系统A和业务系统B都会在客户端写入标志登录状态的cookies,其中有且仅有SSO系统保存有用户密码等私密信息,业务系统A和B仅只可访问到用户标识信息,这样也很好地保证了用户信息的安全性。

37.uuid唯一性

38.数据库3范式(https://blog.csdn.net/zymx14/article/details/69789326)

39.秒杀活动不用redis,怎么用java代码实现

40.5万的访问量怎么设计数据库?不需要考虑;100万就要分库分表,加缓存了(读写分离,见46题)

41.int和Integer区别

42.进程和线程的区别

43.限时秒杀

44.网络爬虫

45.http和https

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
  2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
  3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
  
46.数据库分库分表(垂直和水平切分)和读写分离(https://blog.csdn.net/u013421629/article/details/78793966)

47.前后端分离

http://jbcdn2.b0.upaiyun.com/2017/07/67e8579ee2214313c2b2984471596e35.png

48.同步阻塞,异步非阻塞区别:

49.Redis缓存失效机制(延迟失效机制和主动失效机制)

延迟失效机制即当客户端请求操作某个key的时候,Redis会对客户端请求操作的key进行有效期检查,如果key过期才进行相应的处理,延迟失效机制也叫消极失效机制。
主动失效机制也叫积极失效机制,即服务端定时的去检查失效的缓存,如果失效则进行相应的操作。

50.设计模式

51.final、finally与finallize区别
final:

当用final修饰类的时,表明该类不能被其他类所继承。当我们需要让一个类永远不被继承,此时就可以用final修饰,但要注意:final类中所有的成员方法都会隐式的定义为final方法。

finally:

finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。

finalize:

finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。

52.对于财务double、float数据是怎么处理的

public class testUtil {
	public static void main(String[] args) {
		System.out.println(0.05+0.044);
		System.out.println(0.05-0.04);
		System.out.println(0.05*0.042);
		System.out.println(0.05/0.042);
	}
}
运行结果:
0.094
0.010000000000000002
0.0021000000000000003
1.1904761904761905
解决代码:
import java.math.BigDecimal;
 public class ArithUtil {
	public static double add(double a, double b){
		BigDecimal b1 = new BigDecimal(Double.toString(a));
		BigDecimal b2 = new BigDecimal(Double.toString(b));
		return b1.add(b2).doubleValue();
	}

public static double sub(double a, double b){
	BigDecimal b1 = new BigDecimal(Double.toString(a));
	BigDecimal b2 = new BigDecimal(Double.toString(b));
	return b1.subtract(b2).doubleValue();
}

public static double mul(double a, double b){
	BigDecimal b1 = new BigDecimal(Double.toString(a));
	BigDecimal b2 = new BigDecimal(Double.toString(b));
	return b1.multiply(b2).doubleValue();
}

public static double div(double a, double b, int 10){//10代表精度
	if(scale < 0){
		throw new IllegalArgumentException("小学怎么学的?");
	}
	BigDecimal b1 = new BigDecimal(Double.toString(a));
	BigDecimal b2 = new BigDecimal(Double.toString(b));
	return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static void main(String[] args) {
		System.out.println(ArithUtil.add(0.05, 0.044));
		System.out.println(ArithUtil.sub(0.05, 0.04));
		System.out.println(ArithUtil.mul(0.05, 0.042));
		System.out.println(ArithUtil.div(0.05, 0.042));
	}
运行结果:
0.094
0.01
0.0021
1.1904761905
优先推荐 BigDecimal(String val)构造方法。
理由: BigDecimal(double val) 中的double假设为0.1  但是实际上它有可能是0.100000000000000000000005555。而 BigDecimal(String val) 中"0.1"即为0.1。
(float也是如此处理)

53.Hibernate中的get和load的区别

load加载方式

当使用load方法来得到一个对象时,此时hibernate会使用延迟加载的机制来加载这个对象,当使用session.load() 方法加载一个对象的时候,并不会发出SQL语句,这个对象其实就是一个代理对象,而这个代理对象只是保存实体对象的id值,只有当我们使用这个对象,得到其他属性的时候,这个时候才会发出SQL语句,从数据库中查询相对于的对象

get加载方式

相对于load的延迟加载方式,get就直接的多,当我们使用session.get()方法来得到一个对象时,不管我们使不使用这个对象,此时都会发出sql语句去从数据库中查询出来:

如果对象不存在(报错区别)

如果这个对象不存,通过get方式,去数据库中查询出该对象,但是这个不存在,所以id值页不存在,所以此时对象是null,所以就会报NullPointException的异常了(空指针异常)。
如果使用load方式来加载对象,当我们试图得到这个不存在的对象 的id值的时候,此时会报ObjectNotFoundException异常(对象未找到异常)

54.为什么使用redis?redis挂掉怎么办

55.ActiveMQ在哪里使用?消息丢失怎么办

56.CAS无锁技术

https://www.cnblogs.com/wyq178/p/8965615.html
https://www.jianshu.com/p/f714c440d0cb

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KevinDuc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值