Java开发实习面试总结(49分钟)

前述:

在这里记录总结一下第一次面试经历。
前段时间投的简历,这两天准备期末考试(怂,就靠这两冲刺那。。),把面试的事搁置了,昨天下午HR突然打电话来直接要求技术面试,然后我只能说不方便了。。。明天十一点可以吗。。。可以!

温馨提示:面试还是得早点就做好准备的(我之前准备了,利用这几个小时好温习一下)。

正文:

不说那么多废话了,开始面试问题吧。

1、先介绍一下自己吧

啦啦啦啦。。。就介绍完了,建议尽量提前写一下自我介绍的稿子。

2、说一下集合框架吧,了解哪些接口、类

list接口:存储不唯一的(可重复),有序的元素。
set接口:存储不可重复元素,无序的元素。
map接口:使用键值对进行存储元素。

3、list包含哪些类

常用的有LinkedList和ArrayList两个,(当时没记起来Vector和Stack)

4、能说一下LinkedList和ArrayList的区别是什么吗

  • 两者都是不同步的,即线程不安全的。
  • 从底层数据结构来讲,ArrayList是Object数组实现的,LinkedList是由双向链表构成的。
  • 由数据结构实现可以得出,LinkedList不支持快速随机访问,后者是支持的。
  • 存储所用的空间LinkedList更多一些,它需要存储前驱后继节点。

5、那两者谁的插入元素效率更高一些呢?

(当时紧张到说了句ArrayList。。。蠢哭自己了,连忙道歉)
是LinkedList,从它的底层数据结构就能看出来,LinkedList只需要断开链接即可,而ArrayList需要进行大量元素的移动后插入。

6、可以讲一下HashMap中的put方法的实现过程吗

(这道题也就是间接问你关于hashmap的数据结构了)
这得从它的底层数据结构说起,HashMap的是由数组+链表的结构实现的(当时忘了阈值超过8,演化为红黑树这一点了,面试完才想起来没说),它的内部封装了一个Entry数组,该数组也是一个哈希数组,故而存在哈希冲突的问题,HashMap是通过链地址法来解决冲突问题的,在每一个数组节点下封装一个单链表,所以put()方法添加一个新元素时先通过计算该元素的hash值,再通过hash&(length-1)确定该元素在Entry数组中的下标位置,若无元素则添加,若存在元素再通过equals方法来判断该元素是否在该链表中,如果不存在则放在头结点位置,如存在则不添加。

7、当数组值达到峰值时,怎么进行扩展

hashmap中有两个构造参数,一个初始容量(默认16),另一个为加载因子(默认0.75),当当前存储大于初始容量与加载因子的乘积值时,则进行扩容操作,每次已二倍的速率增长,最大值为2*30(幂次)。
扩容是新建了一个数组,会重新计算hash来获取元素的新位置,所以扩容是一个相当耗时的操作。

8、数据库用的多不,说一下数据库

平时用MySQL比较多一些。

9、数据库优化有哪些方法(简历上写了。。)

(这一块不是很熟,答的不好)

  • 选择合适的字段,尽量把字段设置为not null,这样查询就无需比较null值。
  • 使用关键字查询(left、join、on)查询代替子查询。
  • 使用union联合查询,手动创建临时表。
  • 开启事务,当数据库执行多条语句出现错误时,事务会回滚,可以维护数据库完整性。
  • 使用外键,事务可以维护数据的完整性,但不能保证数据的关联性,使用外键可以保证。
  • 使用索引,索引是提高数据库性能的常用方法,特别是对于max、min、order by查询时。
  • 优化查询语句的书写。

10、可以说一下事务吗

(竟然紧张到忘记说ACID了,直接说了事务隔离级别。。。蠢了)
ACID大家应该都清楚吧,原子性、一致性、隔离性、永久性。

隔离级别包括四个级别:

  • read_uncommited:最低隔离级别,允许读取未提交的数据,造成(脏读、幻读、不可重复读)
  • read_commited:允许读取已提交数据,阻止了脏读,但还存在幻读、不可重复读
  • repeatable_read:可重复读,多次读取结果一致,阻止脏读、不可重复读,但存在幻读
  • serializable:最高级别,服从ACID,依次执行,影响性能

11、脏读是什么?幻读是什么?

脏读:发生在一个事务A读取了被另一个事务B修改,但是还未提交的数据。假如B回退,则事务A读取的是无效的数据。

幻读 :幻读发生在当两个完全相同的查询执行时,第二次查询所返回的结果集跟第一个查询不相同。

12、数据库索引的数据结构是怎样的?

索引的数据结构包含B+树和哈希表两种。一般用B+树比较多(接下来就是无限的B+树怒怼环节了,晕)

13、说一下B+树的定义吧

读者可以自行百度查看。推荐阅读(https://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html)

B+树是B树的一种变形。
B树定义
M表示阶数。

  • 多路搜索树,不是二叉的。
  • 根节点至少有两个子节点【2,M】
  • 除根节点以外的非叶子结点的儿子数是【M/2,M】
  • 每个节点至少存放 M/2-1(取上整)和至多M-1个关键字。(至少两个)
  • 非叶子结点的关键字个数:指向儿子的指针数 + 1
  • 所有的叶子结点在同一层

B树特点

  • 任何一个关键字仅出现在一个结点中
  • 搜索有可能在非叶子结点结束
  • 其性能相当于在关键字全集内做一次二分查找

一棵m阶的B+树和m阶的B-树的差异在于

  • 有k个子结点的结点必然有k个关键码;
  • 非叶结点仅具有索引作用,跟记录有关的信息均存放在叶结点中。
  • 树的所有叶结点构成一个有序链表,可以按照关键码排序的次序遍历全部记录。
    B+树的特点
  • 关键字在叶子结点中,并且有序。
  • 不可能在非叶子结点命中。
  • 非叶子结点相当于索引,叶子结点相当于存储层。
  • 更适合文件索引系统。

14、为什么使用B+树做索引的数据结构,优势在哪里

(这一部分不太懂,当时疯狂说深度低,二叉顺序访问之类的。。。面试官引导磁盘访问效率和内存访问效率时间量级问题,我也很晕菜啊。。。下来百度学习了一下)
一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。

磁盘存取原理
索引一般以文件形式存储在磁盘上,索引检索需要磁盘I/O操作。与主存不同,磁盘I/O存在机械运动耗费,因此磁盘I/O的时间消耗是巨大的,一般是毫秒级别,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存

B+树的优点

  • 由于B+树在内部节点上不含数据信息,因此在内存页中能够存放更多的key。 数据存放的更加紧密,具有更好的空间局部性。因此访问叶子几点上关联的数据也具有更好的缓存命中率。
  • B+树的叶子结点都是相链的,因此对整棵树的便利只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。

15、说一下网络七层模型

(当时只记起来五层模型。。。)
七层模型
物理层—数据链路层—网络层—传输层—会话层—表示层—应用层
五层模型
物理层—数据链路层—网络层—传输层—应用层

16、说一下TCP的三次握手和四次挥手

三次握手

  • 客户端发送一个SYN请求连接,服务端收到连接请求
  • 服务端收到请求之后返回一个ACK的确认请求和SYN
  • 客户端收到之后再次发送一个ACK的确认码

四次挥手:(可以理解为三次挥手+半关闭)
终止连接一般是由客户端发起的。

  • 客户端发送一个FIN断开连接请求
  • 服务端收到该请求之后,先返回一个ACK的确认码
  • 等待服务端当前正在传输的数据传输完成之后,服务端发送一个FIN的终止连接请求
  • 客户端接受到服务端请求之后,给服务端返回一个ACK的确认码,至此终止连接完成

17、如何理解TIME-WAIT

(当时把TIME-WAIT和停止等待协议弄混了。。。说了半天ARQ)

TIME_WAIT是TCP协议用以保证被重新分配的socket不会受到之前残留的延迟重发报文影响的机制,是必要的逻辑保证。

可以理解为主动关闭连接的一方,要停留在TIME-WAIT状态,等待2*MSL(4分钟,Centos7上默认配置的值是1分钟)时间才可以再次回到CLOSED状态,在等待期间该端口(socket)不能被回收使用,即不能正常连接请求。具体现象是对于一个处理大量短连接的服务器,如果是由服务器主动关闭客户端的连接,将导致服务器端存在大量的处于TIME_WAIT状态的socket, 甚至比处于Established状态下的socket多的多,严重影响服务器的处理能力,甚至耗尽可用的socket,停止服务。

18、说一下Spring的IOC和AOP

IOC:控制反转,是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。IOC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。

AOP:面向切面编程,能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

19、AOP是如何实现的?

AOP是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib ,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理。

20、cglib代理怎么实现?

CGlib是一个字节码增强库,为AOP等提供了底层支持。

通过实现MethodInterceptor接口,重写其中的Intercept方法(拦截器)

21、SpringMVC的请求过程

图片来自
(1)客户端(浏览器)发送请求,直接请求到 DispatcherServlet。

(2)DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。

(3)解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由 HandlerAdapter 适配器处理。

(4)HandlerAdapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑。

(5)处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View。

(6)ViewResolver 会根据逻辑 View 查找实际的 View。

(7)DispaterServlet 把返回的 Model 传给 View(视图渲染)。

(8)把 View 返回给请求者(浏览器)

22、说说IO吧

一些基本的输入输出流介绍。

23、NIO是同步阻塞的吗?还有什么阻塞?

它是同步非阻塞的,还有异步非阻塞的AIO;

NIO的特性/NIO和IO的区别
  • IO流是阻塞的,NIO不是阻塞的;
    也就意味着在读写数据期间,IO流的线程是被阻塞的,不能去干其他事情,而NIO是可以进行非阻塞的IO操作的,单线程中从通道(双向通道,可读可写)读取数据到buffer,同时继续做别的事情,当数据读到buffer中之后再去继续执行数据的操作;
  • IO是面向流的,NIO是面向缓冲区的;
    Buffer是一个对象,它包含了你要读取和写入的数据,在NIO库中,所有数据都是由缓冲区处理的。在读取数据时是读到缓冲区的,在写入数据时是写到缓冲区的。任何时候访问NIO的数据都是需要通过缓冲区操作的;
  • NIO是有选择器的,IO是没有的;
    选择器用于单线程处理多个通道。因此它需要较少的线程来处理这些通道,线程之间的切换时昂贵的,为了提高效率选择器是很有用的;

24、了解过Netty吗?

(没有啊。。。)

面试官:好了,面试就到这吧,有什么想问的吗?
我:emmm,面试的不是很好,准备不充分。。。
面试官:比大部分人好多了(我心里有b数的。。)
我:嗯嗯,谢谢面试官。
面试官:好的,那就这样了,拜拜!
我:恩,拜拜!

希望下次可以面试的更好一点,加油吧!

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页