新国都Java面经附参考答案(完结)
新国都 Java 面经 附参考答案(完结)
面试问题
• 1.自我介绍
• 2.熟悉 Java 中有哪些 集合?
• 3.ArrayList 和 LinkedList 区别
• 4.说说 JVM 内存区域
• 5.那你说一下对象从创建到销毁过程
• 6.什么时候引起 full gc,有什么危害
• 7.SQL 优化手段。你知道哪些?
• 8.事务的四大特性
• 9.MySQL 如何保证事务的原子性
• 10.分布式事务
• 11.@Transactional 如何指定隔离级别
• 12.Spring 中 IOC 和 AOP 的理解
• 13.如何进行依赖注入,byName 和 byType 区别
• 14.说一个自己熟悉的项目,讲讲收获(实习或简历上的项目)
• 15.手写单例模式
• 16.反问
参考答案
这里先说清楚,参考答案哈,不可能每个点都讲的很清楚,毕竟,面试很多时候是看你是
否回答到点上。
1、自我介绍
大众化的回答:
面试官你好,我叫张三,河南人,毕业于 XX 大学,从 XX 年毕业后就一直从事 java 开
发,差不多 3 年了吧。来贵公司面试,寻求一份 java 开发工作。
自我介绍要说几个点:你是谁,你的优点是什么?这么多年你干了啥?在学校获得过什么
奖?对哪些技术有深入研究?是否有高并发系统的设计?是否参与过什么大型项目?
总之,把你有的家底都亮出来,让人家知道你哪方面相对比较强。
2、熟悉 Java 中有哪些 集合?
Java 的集合类型主要有 3 种:set(集)、list(列表)和 map(映射)。
List(有序、可重复):List 里存放的对象是有序的,同时也是可以重复的,List 关注的是索
引,拥有一系列和索引相关的方法,查询速度快。因为往 list 集合里插入或删除数据时,
会伴随着后面数据的移动,所有插入删除数据速度慢。常用实现类:ArrayList、
LinkedList。
Set(无序、不能重复):Set 里存放的对象是无序,不能重复的,集合中的对象不按特定的
方式排序,只是简单地把对象加入集合中。常用实现类:HashSet。
Map(键值对、键唯一、值不唯一):Map 集合中存储的是键值对,键不能重复,值可以重
复。根据键得到值,对 map 集合遍历时先得到键的 set 集合,对 set 集合进行遍历,得到
相应的值。常用实现类:HshMap、Hashtable、ConcurrentHashMap。
面试官可能会深入的对某个集合框架实现类进行深入的追问,这是后话哈,能回答上面基
本上可以了。
3、ArrayList 和 LinkedList 有什么区别
第一点:他们的底层数据结构不同,ArrayList 底层是基于数组实现的,LinkedList 底层是
基于单链表实现的。
第二点:由于底层数据结构不同,他们所适用的场景也不同,ArrayList 更适合随机查
找,LinkedList 更适合删除和添加,查询、添加、删除的时间复杂度不同。
第三点:ArrayList 和 LinkedList 都实现了 List 接口,但是 LinkedList 还额外实现了 Deque
接口,所以, LinkedList 还可以当做队列来使。
第四点:时间复杂度,ArrayList:查询 O(1),增删可能涉及数组扩容和[拷贝] (不是
100%) 。LinkedList:查询 O(N),增删 O(1),但增删要先找到元素位置 。
4、说说 JVM 内存区域
JVM 内存区域也通常称之为运行时数据区:程序计数器、虚拟机栈、本地方法栈、方法
区、堆。
其中,方法区和堆是线程共享的。而程序计数器、java 虚拟机栈和本地方法栈是线程私
有。
程序计数器:字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控
制。在多线程的情况下,程序计数器用于记录当前线程执行的位置。不会出现 OOM。
虚拟机栈:每个线程都有自己的虚拟机栈,虚拟机栈的生命周期和线程一致。每次方法的
调用,产生一个栈帧并入栈,方法调用完毕该栈帧就出栈。栈帧里包含局部变量表、操作
数栈、动态链接和方法返回地址。可能会出现栈溢出,也可能会出现 OOM。
本地方法栈:类似虚拟机栈,不过对应的是虚拟机使用到的本地 native 方法。
堆:基本上所有对象都在堆中创建,堆又分为新生代和老年代,新生代又分为 Eden 区、
survivor0,survivor1 (有时也叫做 from 区、to 区) ,Eden:survivor0:survivor1=8:1:1
(默认)。可能会出现 OOM。大部分对象都是在 Eden 区创建和灭亡,但如果对象太大
了,可能会直接在老年代里创建。Eden 区创建,如果没背回收,就到 survivor0,如果又
没被回收,就到 survivor1,survivor0 和 survivor1 相互进行拷贝,到达一定程度就会到
老年代。JDK1.7 及其之前堆内存被分为: 新生代+老年代+永久代。JDK1.8 及其之后堆内
存逻辑上分为三部分:新生区 +老年代 + 元空间。
方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码
等数据。 方法区是一种规范,JDK7 之前使用永久代实现,JD8 及以后,采用元空间实
现。
JDK1.7 之前运行时常量池逻辑包含让字符串常量池存放在方法区发, 此时 hotspot 虚拟机
对方法区的实现为永久代。
JDK1.7 把 字符串常量池、静态变量拿出来放在了堆中,但是其他的仍在方法区(永久
代)。
JDK1.8 hotspot 移除了永久代,使用元空间(Metaspace)取而代之,这时候字符串常量池、
静态变量还在堆,运⾏时常量池还在⽅法区。
5、那你说一下对象从创建到销毁过程
比如下面这段代码:
Student stu = new Student(“田哥”); stu.add(); stu=null;
• 用户创建了一个 Student 对象,运行时 JVM 首先会去方法区寻找该对象的类型信息,
没有则使用类加载器 classloader 将 Student.class 字节码文件加载至内存中的方法
区,并将 Student 类的类型信息存放至方法区。
• 接着 JVM 在堆中为新的 Student 实例分配内存空间,这个实例持有着指向方法区的
Student 类型信息的引用,引用指的是类型信息在方法区中的内存地址。
• 在此运行的 JVM 进程中,会首先起一个线程跑该用户程序,而创建线程的同时也创
建了一个虚拟机栈,虚拟机栈用来跟踪线程运行中的一系列方法调用的过程,每调用
一个方法就会创建并往栈中压入一个栈帧,栈帧用来存储方法的参数,局部变量和运
算过程的临时数据。上面程序中的 stu 是对 Student 的引用,就存放于栈中,并持有
指向堆中 Student 实例的内存地址。
• JVM 根据 stu 引用持有的堆中对象的内存地址,定位到堆中的 Student 实例,由于堆
中实例持有指向方法区的 Student 类型信息的引用,从而获得 add()方法的字节码信
息,接着执行 add()方法包含的指令。
• 将 stu 指向 null
• JVM GC
6、什么时候引起 Full GC,有什么危害
GC:garbage collection ,在通常意义上大家所说的 Full GC 为一次特殊 GC 行为的描述,
这次 GC 会回收整个堆的内存,包含老年代,新生代,metaspace 等 。Full GC 的全过程中
所有用户线程都是处于暂停的状态 ,也就是所谓的 STW(stop the world )。
7、SQL 优化手段,你知道哪些?
1、开启查询缓存,优化查询
2、explain 你的 select 查询,这可以帮你分析你的查询语句或是表结构的性能瓶颈。
EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索
和排序的
3、当只要一行数据时使用 limit 1,MySQL 数据库引擎会在找到一条数据后停止搜索,而
不是继续往后查少下一条符合记录的数据
4、为搜索字段建索引
5、使用 ENUM 而不是 VARCHAR,如果你有一个字段,比如“性别”,“国家”,“民族”,“状
态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不
是 VARCHAR。
6、Prepared StatementsPrepared Statements 很像存储过程,是一种运行在后台的 SQL 语
句集合,我们可以从使用 prepared statements 获得很多好处,无论是性能问题还是安全
问题。Prepared Statements 可以检查一些你绑定好的变量,这样可以保护你的程序不会
受到“SQL 注入式”攻击
7、垂直分表
8、选择正确的存储引擎
说个三五种基本上过关,越多越好。
8、事务的四大特性
传说中的 ACID
1、原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介
绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果
操作失败则不能对数据库有任何影响。
2、一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个
事务执行之前和执行之后都必须处于一致性状态。
拿转账来说,假设用户 A 和用户 B 两者的钱加起来一共是 5000,那么不管 A 和 B 之间如
何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是 5000,这就是事务的
一致性。
3、隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启
的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
即要达到这么一种效果:对于任意两个并发的事务 T1 和 T2,在事务 T1 看来,T2 要么在
T1 开始之前就已经结束,要么在 T1 结束之后才开始,这样每个事务都感觉不到有其他事
务在并发地执行。
4、持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是
在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
例如我们在使用 JDBC 操作数据库时,在提交事务方法后,提示用户事务操作完成,当我
们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现
了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完
毕,但是数据库因为故障而没有执行事务的重大错误。
9、事务如何保证原子性
MySQL 原子性的保证是利用了 undo log。undo log 名为回滚日志,是实现原子性的关
键,当事务回滚时可以撤销全部已经成功执行的 sql 语句,他须要记录你要回滚的相应日
志信息。undo log 记录了这些回滚须要的信息,当事务执行失败或调用了 rollback,致使
事务须要回滚,即可以利用 undo log 中的信息将数据回滚到修改以前的样子。
10、分布式事务
当我们在跨多个服务,操作多个数据库时。就会涉及分布式事务,需要操作的资源位于多
个资源服务器上,而应用需要保证对于多个资源服务器的数据的操作,要么全部成功,要
么全部失败。本质上来说,分布式事务就是为了保证不同资源服务器的数据一致性。
分布式事务解决方案几乎都是柔性事务,常见的有 2PC/3PC、TCC、MQ 最终一致性解决
方案,至于工作中用哪种方案,需要根据业务场景选取,2PC/3PC、TCC 数据强一致性
高,而 MQ 是最终数据一致。
@Transactional 如何指定隔离级别
在使用时,@Transactional(isolation= Isolation.DEFAULT)中的 isolation 就是我们的隔离
级别,对应有一个枚举 Isolation,这个枚举里定了四种隔离级别:
DEFAULT(对应数据库默认隔离级别)、READ_UNCOMMITTED、READ_COMMITTED、
REPEATABLE_READ、SERIALIZABLE
11、Spring 中 IOC 和 AOP 的理解
Spring IOC
1.IOC 控制反转,是指创建对象的控制权转移,以前创建对象的主动权和时机是由自己把
控的,而现在这种权力转移到 spring 容器中,并由容器根据配置文件去创建实例和管理
各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI 依赖注
入,和控制反转是同一个概念的不同角度的描述,即应用程序在运行时依赖 IOC 容器来动
态注入对象需要的外部资源
2.最直观的表达就是,IOC 让对象的创建不用去 new 了,可以由 spring 自动生产,使用
java 的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的
方法
3.Spring 的 IOC 有三种注入:setter 方法注入,构造器注入,接口注入
Spring AOP
OOP 面向对象,允许开发者定义纵向关系,但并适用于定义横向的关系,导致了大量代
码的重复,而不利于各个模块的重用。
AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多
个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名
为“切面(asoect)”,减少系统中的重复代码,降低了模块间的耦合度,同时提高系统的
可维护性。可用于权限认证、日志、事务处理等。
Spring AOP 中的动态代理主要有俩种方式,JDK 动态代理和 CGLIB 动态代理
12、如何进行依赖注入,byName 和 byType 区别
byName 就是通过 Bean 的属性名称(id 或 name)自动装配。当一个 bean 节点带有
autowire byName 的属性时,需要注意下面三点:
(1)将查找其类中所有的 set 方法名,例如 setCat,获得将 set 去掉并且首字母小写的字
符串,即 cat。(2)去 spring 容器中寻找是否有此字符串名称 id 的对象。(3)如果有,
就取出注入;如果没有,就报空指针异常。
byType 就是通过 Bean 的 Class 类型来自动装配。使用 autowire byType 首先需要保证:
同一类型的对象,在 spring 容器中唯一。如果不唯一,会报不唯一的异常。
14、说一个自己熟悉的项目,讲讲收获(实习或简历上的项目)
这个肯定要说自己最熟悉的项目咯,先说业务,如果是负责人,那就要项目核心业务给说
清楚,如果是负责部分,那就把自己负责的那部分能说清楚。然后说项目技术栈,最后再
说项目并发量如何?数据量如何?解决过什么问题?
15、手写单例模式
这个得需要自己事先准备过,可以写双重检查模式,也可以写枚举式。自己看着办。可以
参考我之前写的一篇文章。
16、反问
面试最后一个环节就是:你还有什么想我的吗?
有时候是客气时这么反问,有时候又是真的反问,所以,此时需要谨慎提问。别问一些无
聊的话题,你们公司什么会调薪?你们加班多吗?但是你很牛,到也不怕,一般人还是别
问哈。
牛客链接:https://www.nowcoder.com/discuss/1097273