首先,这次没有让我自我介绍。直奔主题。
问题1:整形有哪几种?
int,long,short,byte(但这个问题我没回答完整,不应该)
问题2:byte的范围有多大?
懵了,没想到会问这个,但是我圆场的还可以,我说我对int类型的范围记得比较清楚,然后有心计的提到了自己最近在看HashMap的源码(为什么不直接用hashcode值作为key,这里用到了int的一个范围),然后我表明自己对byte的范围确实没有太过注意(今后要注意)。后来没错, 开始问我HashMap
问题3:讲一下HashMap为什么能够读这么快?
也是迷。我后来冷静下来,从一开始讲。我从HashMap的结构开始说起。
在jdk1.8之前,hashMap的结构是数组加链表的形式。
内部类是Entry[],然后每个Entry又是一个单链表。那么我们在put数据的时候,先根据hash()算法求出hashcode,然后取模。
(这里我又扯了一下1.7和1.8的扰动算法的区别,一个9次一个2次)。
然后取出对应的下标index。在开始插入。那么读数据也类似,先算hashcode, 然后计算index,找数组元素,遍历链表。同时我又提到了遍历链表的两个情况:
index>长度的一半,从后往前遍历
index<长度的一半,从前往后遍历。
然后就没了,我可能感觉get操作也回答不出什么东西,他都没问我太深的问题。
问题4:spring涉及到的设计模式有什么?
1.首先回答了工厂模式,BeanFactory,我这里提到了自己使用hibernate的时候,bean都是从工厂里面取出来的。(注意,不要回答的太简单,尽量有一个实际的演示过程)。
2.单例模式:bean默认为singlton,后来我提到了他和prototype的区别是什么。
然后他紧接着问:你刚刚提到的是bean的一个作用域对吧,那么bean还有哪些作用域呢?回答:request和session。
3.我说了委派模式:提到了springmvc的DispatchServlet。
问题5:redis的缓存击穿?缓存穿透?缓存雪崩?
- 缓存雪崩:缓存同一时间内大面积的失效,所以大量的请求会落到数据库上,造成数据库短时间内收到大量请求而崩掉
解决方案:我提到了两种
1.将缓存数据的过期时间设置为随机。
2.给每一个缓存设置一个过期的标记,比如过期了设置为true,否则false
- 缓存穿透:是指缓存和数据库中都没有这个数据,但是同时又有大量请求去访问该数据,同样造成数据库的一个崩盘
解决方案:采用接口增加校验。我这里结合了具体情况:
比如我们的数据库id一般来说不为0对吧?然后我说了在主题类中添加Blank注解还有NotNull注解,还有Max,Min等等。对数据进行一个初步检验
- 缓存击穿:指的是缓存中没有但是数据库中有这个数据,(一般是缓存过期了)
解决方案:设置热点数据为永不过期。
问题6:redis的基本数据类型有什么?
很简单:Set,String,List,Sorted_set,Hash
问题7:https和http的区别是什么?
- https的端口是443,http的端口是80
- https有数据加密过程,所以更加安全
- https在使用的过程中更加占用cpu资源(因为要数据加密)
问题8:说下类的加载机制,双亲委派机制。为什么这么设计?
类在收到加载请求的时候,并不会马上自己处理,而是把这个请求交给他的父类加载器完成,最顶端的加载器是Bootstrap启动类加载器。如果父加载器无法处理,再返回给子加载器让他自己完成。
为什么这样设计?
首先明确一点:jvm如何认定两个对象同属于一个类型,必须同时满足下面两个条件:
1.都是用同名的类完成实例化的。
两个实例各自对应的同名的类的加载器必须是同一个。比如两个相同名字的类,一个是用系统加载器加载的,一个扩展类加载器加载的,两个类生成的
2.对象将被jvm认定为不同类型的对象。
所以,为了系统类的安全,类似“ java.lang.Object”这种核心类,jvm需要保证他们生成的对象都会被认定为同一种类型。即“通过代理模式,对于 Java 核心库的类的加载工作由引导类加载器来统一完成,保证了 Java 应用所使用的都是同一个版本的 Java 核心库的类,是互相兼容的”。
问题9:说下有哪几种GC?
年轻代:
Serial(单线程)
ParNew(Serial的多线程版本)
老年代:
Serial Old(单线程)
ParNew Old(Serial的多线程版本)
提了一下CMS垃圾回收器
然后扯了一下G1 说了一下他的作用范围是老年代加年轻代
问题10:说下ArrayList和LinkedList的区别?
- 首先ArrayList是基于数组的集合,而LinkedList是基于链表的集合
- ArrayList适用于查询较多的场景,而LinkedList适用增删较多的场景
- 说了为什么会适用这样的场景,因为ArrayList有数组索引,查找块,但是进行增加和删除操作的时候,因为要维护索引,所以会比较麻烦。
而LinkedList的话只用改变指针的引向即可。
问题11:mybatis的 # 和$的区别是什么?
- #传入的数据都将当成字符串,会对传入的数据自动加入引号,有一个预编译处理
- $则将传入的数据显示在sql中,因此我提到了容易受到sql注入攻击
(比如参数为"drop table xxx")那有些数据库执行了怎么办,破坏表。
问题12:hibernate的三个状态是什么:
持久,游离态,瞬时态:(我说了下三者之间是如何切换的)
- 瞬时态:刚通过new出来的对象就是瞬时态的
- 游离态:如果session经历了flush或者clear或者close,那么对象编程游离态
- 持久态:我说顾名思义,因为他的数据已经被持久化到数据库当中了
然后说了下save()会将瞬时态的实例变成持久态
游离态的实例通过update()或者saveOrUpdate()可以变成持久态
问题13:zookeeper的选举机制是什么?
给了我一个场景,一共7台机器,编号分别为1-7,问我哪台机器是leader?
我毫不犹豫的回答:4号机器
然后让我说下具体的流程:我先说了选举算法是FastLeaderElection
- 机器1启动,编号1,先投给自己一票,此时其他机器还没有启动,因此不能进行信息的交换,1就在这等着吧!然后1处于looknig状态
- 机器2启动,编号2,先投自己一票,此时机器1和2进行比较,2的编号大,胜出。但是此时的机器启动量只有2台,没有超过半数,同样处于looking状态
- 机器3启动,编号3,先投自己一票,此时机器123进行比较。3胜出,依旧处于looking状态,理由同上
- 机器4启动,编号4,先投自己一票,机器1234比较,4胜出,此时4台机器启动着,超过半数,4选举为leader!123成为follower
- 机器5,6,7启动后,虽然编号大于4,但是此时已经有leader了,所以5,6,7只能成为follower。
问题14:问了我RabbitMQ怎么用到的,问了我如果MQ出现消息的积压怎么办?
答:在rabbit可视化界面创建队列和交换机exchange,在后台实现服务的绑定。
MQ的消息挤压怎么办:
- 紧急扩容:增加消费者的个数对消息队列里面的消息进行消费
- 批量重导:可以把大量的消息先拿出来,放到另外的机器当中,先保存着,当你环境压力小的时候,你在拿出来放到队列里面去消费
问题15:数据库:索引在什么条件下会失效?
1.like查询的时候第一个通配符是%
2.or查询的前后没有同时使用索引
3.数据类型出现隐式转换(这个我没回答上来,就说了以上两点,很可惜)
问题16:问了我StringBuffer和StringBuilder的区别是什么?
- 首先说了他们两个的相同点,都是final修饰的类,然后我们一般都用他们作为字符串的拼接,我讲了append()方法
- 然后说了不同点:StringBuffer线性安全,也因此效率低(因为有加锁操作)而StringBuilder非线性安全
问题17:问了我事务的4个基本特征?
我笑了笑,这个挺简单的
回答:首先事务的4个基本特征叫ACID,原子性,一致性,隔离性,持久性
- 原子性:事务整体不可分割
- 一致性:事务要么都成功,要么都不成功
- 隔离性:事务一旦开始,不可以去干扰别人
- 持久性:事务一旦开始,无法停止
问题18:问了我mybatis的分页
- 首选我说了下用sql语句分页,limit A,B(你们都懂)
- 然后我说了mybatis自带的rowbounds(大家可能会忽略这个),然后我说我对这个的使用并不是很频繁,我一般用插件pagehelper
后来哭了,他问我为啥要使用这些插件,当然是方便啊,还用问。咳咳
后来我从另一个角度来回答,我说插件是非常便利的,我这里提到了一个插件Hutool,我说他的很多工具类都很好,比如我们数据库订单创建一个唯一Id,可以用UUID,还有日期函数等等。我就从侧面表达了,插件的使用相对来说更方便(因为插件一般都封装了很多底层代码)
问题19:说一下内存溢出和内存泄露的区别?
首先内存泄漏我没说出来
我先说下我怎么说内存溢出的:
我说当你申请的栈深度>栈的最大深度,那么会发生内存溢出
正经答案:
- 溢出: 系统已经不能再分配出你所需要的空间,比如你需要100M的空间,系统只剩90M了,这就叫内存溢出
- 泄露:意思就是你用资源的时候为他开辟了一段空间,当你用完时忘记释放资源了,这时内存还被占用着,一次没关系,但是内存泄漏次数多了就会导致内存溢出。
然后问了我一个实际场景,问我怎么设计:
如果有多个人同时用一个博客,假设有一个人正在写字,那么让其他人能够实时的看到他写出的字呢?
这个我可能答得不是很好:我说我只想到让页面有一个ajax请求,异步的不断的更新,以保证获得最新的数据。但是我觉得考察的不是这个方面,如果大家有什么想法,欢迎大家在评论区分享自己的想法。
(后来我知道用websocket)
最后,还有很多一些简单的问题没有放上来,因为这次的一面,问的总体非常基础,并没有问我一些原理,比如IOC原理,mvc原理,AOP原理,SpringBoot启动原理,自动配置原理。大数据方面的比如MR的过程等等,这些都没问,也就是说,一面偏向于基础(哈哈我准备了好多都没用上),不过面试整体感觉还是顺利的。
这里给大家提一点建议:
- 首先,基础一定要把握好,不要像我一样,byte字节一开始都回答错了,然后范围一定要留意一下。
- 如果问你的题目你不是很熟悉,你可以换个角度去回答,一定不要说我不会,你要把自己的一个思路说出来。
- 学会临时应变,因为他问的东西可能你没听过,比如他问我HashMap为什么取值这么快。我就懵了,一般都问你底层呀,get,put操作呀,这个我还真没听过,但是我把知道的都说出来了。至少让人家知道,你是看过源码的,有自己研究过的!
- 就算问的题目很基础,你也要多看一些深入的原理问题。这样你回答的时候可以穿插一点,至少算个加分项!