cvte补录一面和二面(java后端工程师)
cvte一面和二面(java后端工程师)
2019年一月份参加cvte补录的菜鸟,从秋招以来,网申得到的第一份面试机会(菜鸡一个目不忍视),所以在牛客记录一下。
一面(注:下面的题目有些是在牛客网中收集前面面试过的题目,以及我自己面试的题目)
-
什么样的对象可以当作gcroots
在Java语言里,可作为GC Roots对象的包括如下几种:
a.虚拟机栈(栈桢中的本地变量表)中的引用的对象
b.方法区中的类静态属性引用的对象
c.方法区中的常量引用的对象
d.本地方法栈中JNI的引用的对象 -
switch能否用string做参数
-
在jdk 7 之前,switch 只能支持 byte、short、char、int 这几个基本数据类型以及由于1.5之后的自动拆箱,这四种基础类型对应的封装类也同样支持Byte,Short,Character,Integer。```
Integer num = new Integer(1);switch (num){ case 1: System.out.println("1");break; case 2: System.out.println("2");break; }
当Integer与int比较时,会自动拆箱,转成int类型进行比较。
但如果两个都是Integer类型,就不会自动拆箱成int类型,直接是以Integer类型比较,所以这里有个难理解的点就是,
Integer num1 = 1; Integer num2 = 1; if (num1 == num2){ System.out.println(true); }else{ System.out.println(false); } Integer num3 = 166; Integer num4 = 166; if (num3 == num4){ System.out.println(true); }else{ System.out.println(false); }
输出结果
true false
结果是不是意料之外?为什么num1 == num2,但num3 != num4 ?
因为,首先要明白的一点是,两个Integer类型之间进行比较,是不会触发自动拆箱操作的,即不会转换成int类型,而是直接以Integer类型,只有在有运算逻辑中(加减乘除等,而“==”是逻辑运算符)。在自动装箱时,对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象;而如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象;
- 在jdk1.7后,整形,枚举类型,boolean,字符串都可以
-
SpringMVC执行流程
第一步
用户发起请求到前端控制器DispatcherServlet
第二步
DispatcherServlet请求处理器映射器HandlerMapping查找Handler
可以是根据xml查找,也可以是根据注解查找
第三步
HandlerMapping向DispatcherServlet返回Handler
第四步
HandlerMapping调用处理器适配器HandlerAdapter去执行Handler
第五步
处理器适配器去执行Handler
第六步
Handler执行完给处理器适配器返回ModelAndView
ModelAndView是SpringMVC框架的一个底层对象,包括Model和View
第七步
处理器适配器给DispatcherServlet返回ModelAndView
第八步
DispatcherServlet请求视图解析器View resolver进行视图解析
根据逻辑视图解析成真正的物理视图(jsp等)
第九步
视图解析器向DispatcherServlet返回view
第十步
DispatcherServlet进行视图渲染
第十一步
DispatcherServlet向用户响应结果
-
浅谈Session与Cookie的区别与联系
-
hashmap相关的问题
-
5.1 hashmap源码
-
5.1 hashmap扩容、为什么是2n(2的n次方)扩容
扩容或者初始化容量时,都是以2的n次方扩容,这主要原因是,hashmap定位key的下标的机制决定的。根据源码:public V put(K key, V value) { if (key == null) return putForNullKey(value); // 若“key不为null”,则计算该key的哈希值,然后将其添加到该哈希值对应的链表中。 int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry e = table[i]; e != null; e = e.next) { Object k; // 若“该key”对应的键值对已经存在,则用新的value取代旧的value。然后退出! if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } // 若“该key”对应的键值对不存在,则将“key-value”添加到table中 modCount++; addEntry(hash, key, value, i); return null; } // 返回索引值 // h & (length-1)保证返回值的小于length static int indexFor(int h, int length) { return h & (length-1); }
我们可以看到当put或者get方法时,会先对key进行hashcode获得hash值,然后用hash值和(table长度-1)进行与运算(indexFor方法),从而得到key的table数组的下标,其实除了与运算,还可以直接使用mod取余运算(hash值%(table长度-1))来获得下标位置,但由于在计算机中取余运算很耗时(计组中有学二进制的除法运算会比二进制的直接与运算复杂很多),所以hashmap采用的是运算来定位key的下标。
如果table长度是2的n次方,那么table.length-1的二进制一定是都是1,如length=16,则length-1=15 -> 1111
那么任何一个小于table.length-1的数字跟length-1进行与运算都是它本身,如9->1001,1001 & 1111 = 1001;这样能保证key的分步均匀,减少key的冲突。
但如果不是2的n次方,假设table.length=15,则table.length-1=14 -> 1110,key的hash值认为9,即1001 & 1110 = 1000 ,发现了什么?只要key的hash值的二进制位1的都不能 用了,这样会跟原本应该在***0的位置的key产生冲突,然后hashmap使用的是拉链法解决冲突,所以冲突的key会放到链表中,无冲突的hashmap取值的时间复杂度为O(1),如果冲突,则在链表中查询当前值的时间复杂度为O(n),这严重降低了hashmap的查询料率。
所以不管是在初始化容量时还是在扩容时,jdk会自动帮你选择以2den次方进行扩容。 -
5.2 负载因子为什么是0.75
当创建 HashMap 时,有一个默认的负载因子(load factor),其默认值为 0.75,这是时间和空间成本上一种折衷:增大负载因子可以减少 Hash 表(就是那个 Entry 数组)所占用的内存空间,但会增加查询数据的时间开销,这是因为增大负载因子,那么key的冲突会增大,然后存储到链表的节点,链表的节点查询时间复杂度是O(n),而查询是最频繁的的操作(HashMap 的 get() 与 put() 方法都要用到查询);减小负载因子会提高数据查询的性能,但会增加 Hash 表所占用的内存空间,负载因子越小,table数组的位置就越来被使用。 -
5.3 hashMap为什么线程不安全(hash碰撞与扩容导致)
-
5.4 hashmap冲突的解决方法以及原理分析:
-
5.5 JDK1.8对HashMap有哪些优化
-
5.6 使用类自定义hashmap的key,要重写哪些方法,hashcode方法和equals方法
- 面向对象的设计方法
- 聚集索引区别
-
聚集索引
数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引,所以查询效率快,只要找到第一个索引值记录,其余就连续性的记录在物理也一样连续存放。聚集索引对应的缺点就是修改慢,因为为了保证表中记录的物理和索引顺序一致,在记录插入的时候,会对数据页重新排序。 -
非聚集索引
索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。两种索引都采用B+树结构,非聚集索引的叶子层并不和实际数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针方式。非聚集索引层次多,添加和删除数据时不会造成数据重排。
SQL Sever索引类型有:唯一索引,主键索引,聚集索引,非聚集索引。
MySQL 索引类型有:唯一索引,主键(聚集)索引,非聚集索引,全文索引。(主键就是聚集索引)
- 聚集索引和非聚集索引的根本区别:
- 表记录的排列顺序和与索引的排列顺序是否一致。
- 聚集索引一个表只有一个,非聚集索引一个表可以存在多个。
- 聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续。
- 聚集索引优点:
- 范围查询快,因为一旦具有第一个索引值的纪录被找到,具有连续索引值的记录也一定物理的紧跟其后。
- 字段排序快。
- 非聚集索引优点:
- 非聚集索引比聚集索引层次多,添加记录不会引起数据顺序的重组。
+
-
索引数据结构为啥不用红黑树
-
分布式锁的实现方式
-
解决死锁
-
cglib
cglib是针对类来实现***的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现***。因为采用的是继承,所以不能对final修饰的类进行***。 -
线程池的实现原理,拒绝策略的时机
-
string的继承问题,使用final原因
-
抽象类与接口区别
-
判断SQL语句的执行效率,看哪几个字段
-
索引失效情况
-
多个有序数组合并(这个我当时没有思路,本来想使用归并算法,但归并是在一个数组里面进行分治排序,到现在也没有好的思路,有想法的朋友可以不啬赐教)
-
spring过滤器实现原理
电话面的面试官体验挺好的,有礼貌,但感觉面试官手上有面试题库,因为问的题目跨越比较大。
二面
两轮技术面,一般是一面问基础,二面问项目经历,cvte也是这样。
首先让我自我介绍,我主要是介绍项目经历和实习经历,然后面试官顺着我的项目经验进行提问,以检测我的项目开发能力,因为这些项目都是我真实做过,并且有去了解具体实现细节,所以回答起来都很顺畅,嘻嘻。面试官人很好,不会打断发言,会一直听你解释,点赞。
最后我本以为有需要手撕算法题,因为是在牛客网就进行的视频面试,所以准备了一些算法题,但发现没有,是因为我幸运吗?然而问的是sql语句,让我写查询语句,就一题:
一张分数表里面,有学生id,课程id,分数,然后查询平均分前三的学生id
select studentId,avg(score) as avgScore from S_score group by studentId order by avgScore limit 0,3我也不知道对不对,当时只有这一个想法。
HR面还没开始,有点小慌,听说是50%的刷人率,希望菩萨保佑,哈哈哈哈,大吉大利
本菜鸡博客https://blog.csdn.net/qq_35923749/article/details/85992915
#Java工程师##广州视源电子科技股份有限公司##面经##秋招#