2020年面试题精选30道

1、 简述面向对象的三大特征、五大原则。
特征:
1.封装:封装就是隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别,将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。
2.继承:继承机制允许创建分等级层次的类。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
3.多态:多态同一个行为具有多个不同表现形式或形态的能力。是指一个类实例(对象)的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。
多态的优点有:消耦合,可替换和扩展,接口性,灵活性,简化性
多态的成立添加为:继承,重写,父类引用指向子类


2、 抽象类和接口的区别和各自的应用场景。
抽象类:
1.抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量
2.抽象类不可以被创建对象(实例化)
3. 抽象类中有构造函数,可以定义非抽象方法
4. final ,private , static 不可与abstract一起
接口:1.是用关键字interface定义的。
2. 接口是对外提供的规则。接口是功能的扩展。接口的出现降低了耦合性。
3.在JDK8环境中,接口中的方法不再是只能有抽象方法,他可以有静态方法default方法。
4.声明的变量自动是公开 静态 常量!
区别:1:抽象类只能被继承,而且只能单继承。
接口需要被实现,而且可以多实现。
2:抽象类中可以定义非抽象方法,子类可以直接继承使用。
接口中都有抽象方法,需要子类去实现。
3:抽象类使用的是 is a 关系。
接口使用的 like a 关系。
4:抽象类的成员修饰符可以自定义。
接口中的成员修饰符是固定的。全都是public的。


3、 ==与equals的区别
==方法决定引用值是否指向同一对象
equals()会在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。


4、 请简述HashMap与CurrentHashMap区别,并分别说出jdk.1.7与jdk1.8之间的区别

JDK1.7:ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment实际继承自可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,每个Segment里包含一个HashEntry数组,我们称之为table,每个HashEntry是一个链表结构的元素。初始化有三个参数:initialCapacity:初始容量大小 ,默认16。loadFactor, 扩容因子,默认0.75,当一个Segment存储的元素数量大于initialCapacity* loadFactor时,该Segment会进行一次扩容。concurrencyLevel 并发度,默认16。并发度可以理解为程序运行时能够同时更新ConccurentHashMap且不产生锁竞争的最大线程数,即ConcurrentHashMap中的分段锁个数,即Segment[]的数组长度。如果并发度设置的过小,会带来严重的锁竞争问题;如果并发度设置的过大,原本位于同一个Segment内的访问会扩散到不同的Segment中,CPU cache命中率会下降,从而引起程序性能下降。

JDK1.8:已摒弃Segment的概念,直接用Node数组+链表+红黑树的数据结构来实现,并发控制使用Synchronized和CAS来操作,是优化过且线程安全的HashMap。在JDK1.8中还能看到Segment的数据结构,但是已经简化了属性,只是为了兼容旧版本。

JDK1.8取消了segment数组,直接用table保存数据,锁的粒度更小,减少并发冲突的概率;
JDK1.8存储数据时采用了链表+红黑树的形式,纯链表的形式时间复杂度为O(n),红黑树则为O(logn),性能提升很大;
JDK1.8的实现降低锁的粒度,JDK1.7版本锁的粒度是基于Segment的,包含多个HashEntry,而JDK1.8锁的粒度就是HashEntry(首节点);
JDK1.8版本的数据结构变得更加简单,使得操作也更加清晰流畅,已使用synchronized来进行同步,由于粒度的降低,实现的复杂度增加;
JDK1.8使用红黑树来优化链表,红黑树的遍历效率是很快;
JDK1.8使用内置锁synchronized来代替重入锁ReentrantLock。


5、 请简述GC(垃圾回收机制)的四种算法。
①引用计数
对象增加一个引用时,引用数+1。减少一个时,引用数-1。当进行垃圾回收时,只回收引用数为0的对象。面对互相引用无解,方法比较老,基本弃用

②标记+清除
从根节点遍历标记对象,然后遍历整个堆,清除没有标记的对象。
缺点:运行效率不高,产生了内存碎片,运行时需要暂停应用

③复制
将内存分为2个区域(区域a和区域b),一个区域空着(区域a),另一个区域(区域b)放对象。垃圾回收时,将区域b还在引用的对象复制到空着的区域(区域a)中去,并且当前区域(区域b)清空。如此反复
缺点:复制到a区域的时候,同时进行了内存整理,没有内存碎片。但是需要2倍的内存

④标记+整理
从根节点遍历标记对象,然后遍历整个堆,清除没有标记的对象,并且将有标记的对象压缩到一块的区域内
特点:没有内存碎片,也不需要2倍内存


6、 什么情况下会出现内存溢出。

第一种OutOfMemoryError: PermGen space
发生这种问题的原意是程序中使用了大量的jar或class,使java虚拟机装载类的空间不够
第二种OutOfMemoryError: Java heap space
发生这种问题的原因是java虚拟机创建的对象太多,在进行垃圾回收之间,虚拟机分配的到堆内存空间已经用满了,与Heap space有关。
第三种OutOfMemoryError:unable to create new native thread
这种错误在Java线程个数很多的情况下容易发生


7、 请说出线程池的工作原理。
先启动若干数量的线程,并让这些线程都处于睡眠状态,当客户端有一个新请求时,就会唤醒线程池中的某一个睡眠线程,让它来处理客户端的这个请求,当处理完这个请求后,线程又处于睡眠状态。


8、 什么是悲观锁和乐观锁,俩者有什么区别。
悲观锁假定其他用户企图访问或者改变你正在访问、更改的对象的概率是很高的,因此在悲观锁的环境中,在你开始改变此对象之前就将该对象锁住,并且直到你提交了所作的更改之后才释放锁。悲观的缺陷是不论是页锁还是行锁,加锁的时间可能会很长,这样可能会长时间的限制其他用户的访问,也就是说悲观锁的并发访问性不好。
与悲观锁相反,乐观锁则认为其他用户企图改变你正在更改的对象的概率是很小的,因此乐观锁直到你准备提交所作的更改时才将对象锁住,当你读取以及改变该对象时并不加锁。可见乐观锁加锁的时间要比悲观锁短,乐观锁可以用较大的锁粒度获得较好的并发访问性能。


9、 请说出线程的生命周期。
New(初始化状态)

Runnable(就绪状态)

Running(运行状态)

Blocked(阻塞状态)

Terminated(终止状态)


10、 Jdk1.8都出了什么新功能。
一、接口的默认方法
二、Lambda 表达式
三、函数式接口
四、方法与构造函数引用
五、Lambda 作用域
六、访问局部变量
七、访问对象字段与静态变量
八、访问接口的默认方法
九、Date API
十、Annotation 注解


11、 如何防止死锁。
死锁避免的基本思想:系统对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,如果分配后系统可能发生死锁,则不予分配,否则予以分配,这是一种保证系统不进入死锁状态的动态策略。
如果操作系统能保证所有进程在有限时间内得到需要的全部资源,则系统处于安全状态否则系统是不安全的。

破坏“不可剥夺”条件:一个进程不能获得所需要的全部资源时便处于等待状态,等待期间他占有的资源将被隐式的释放重新加入到 系统的资源列表中,可以被其他的进程使用,而等待的进程只有重新获得自己原有的资源以及新申请的资源才可以重新启动,执行。
破坏”请求与保持条件“:第一种方法静态分配即每个进程在开始执行时就申请他所需要的全部资源。第二种是动态分配即每个进程在申请所需要的资源时他本身不占用系统资源。
破坏“循环等待”条件:采用资源有序分配其基本思想是将系统中的所有资源顺序编号,将紧缺的,稀少的采用较大的编号,在申请资源时必须按照编号的顺序进行,一个进程只有获得较小编号的进程才能申请较大编号的进程。


12、 手写冒泡排序。
int a[] = {23,45,64,34,25,53,34,56,43,54,24};
int temp = 0;
for (int i = 0; i < a.length-1; i++) {
for (int j = 0; j < a.length-1-i; j++) {
if (a[j]>a[j+1]) {
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}


13、 请写出一个单列模式。
确保一个类只有一个实例,并提供一个全局的访问点
饿汉/懒汉模式

private Rabbit rabbit;

public Rabbit getRabbit(){
if(rabbit==null){
rabbit=new Rabbit()
}
return rabbit;
}


14、 简述springmvc的请求流程
第一步:发起请求到前端控制器(DispatcherServlet)

第二步:前端控制器请求HandlerMapping查找 Handler (可以根据xml配置、注解进行查找)

第三步:处理器映射器HandlerMapping向前端控制器返回Handler,HandlerMapping会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象,多个HandlerInterceptor拦截器对象),通过这种策略模式,很容易添加新的映射策略

第四步:前端控制器调用处理器适配器去执行Handler

第五步:处理器适配器HandlerAdapter将会根据适配的结果去执行Handler

第六步:Handler执行完成给适配器返回ModelAndView

第七步:处理器适配器向前端控制器返回ModelAndView (ModelAndView是springmvc框架的一个底层对象,包括 Model和view)

第八步:前端控制器请求视图解析器去进行视图解析 (根据逻辑视图名解析成真正的视图(jsp)),通过这种策略很容易更换其他视图技术,只需要更改视图解析器即可

第九步:视图解析器向前端控制器返回View

第十步:前端控制器进行视图渲染 (视图渲染将模型数据(在ModelAndView对象中)填充到request域)

第十一步:前端控制器向用户响应结果


15、 简述spring的优点,以及什么是aop和ioc,底层的实现原理。
优点:
1.使用Spring的IOC容器,将对象之间的依赖关系交给Spring,降低组件之间的耦合性,让我们更专注于应用逻辑;

2.可以提供众多服务,事务管理,WS等;

3.AOP的很好支持,方便面向切面编程;

4.对主流的框架提供了很好的集成支持,如Hibernate,Struts2,JPA等;

5.Spring DI机制降低了业务对象替换的复杂性;

6.Spring属于低侵入,代码污染极低;

7.Spring的高度可开放性,并不强制依赖于Spring,开发者可以自由选择Spring部分或全部。

spring核心主要两部分:
(1)aop:面向切面编程:扩展功能不是修改源代码实现
(2)Ioc:控制反转,比如有一个类,在类里面有方法(不是静态的方法,创建类的对象,使用对象调用方法,创建类对象的过程,需要new出来对象。

底层:
通过反射,接受到xml中的,然后xml解析循环获取,反射

16、 简述Spring中的注入方式以及事务中的隔离级别和传播行为。
spring实现事务的方式:

? ? ? 1.编码方式
? ? ? 2.spring配置方式
? ? ? 3.注解式

基于AOP技术实现的声明式事务管理,实质就是:在方法执行前后进行拦截,然后再目标方法开始之前创建并加入事务,执行完目标方法后根据执行情况提交或回滚事务.
声明式事务管理又有两种实现方式:基于xml配置文件的方式;另一个实在业务方法上进行@Transaction注解,将事务规则应用到业务逻辑中
一种常见的事务管理配置:事务拦截器TransactionInterceptor和事务自动代理BeanNameAutoProxyCreator相结合的方式

spring事务的隔离级别:有5种

  • DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别
  • 未提交读(read uncommited) :脏读,不可重复读,虚读都有可能发生
  • 已提交读 (read commited):避免脏读。但是不可重复读和虚读有可能发生
  • 可重复读 (repeatable read) :避免脏读和不可重复读.但是虚读有可能发生.
  • 串行化的 (serializable) :避免以上所有读问题.

spring事务的传播行为:7种

PORPAGATION_REQUIRED:支持当前事务,如果不存在 就新建一个(默认)
PROPAGATION_SUPPORTS:支持当前事务,如果不存在,就不使用事务
PROPAGATION_MANDATORY:支持当前事务,如果不存在,抛出异常
PROPAGATION_REQUIRES_NEW:如果有事务存在,挂起当前事务,创建一个新的事务
PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果有事务存在,挂起当前事务
PROPAGATION_NEVER:以非事务方式运行,如果有事务存在,抛出异常
PROPAGATION_NESTED:如果当前事务存在,则嵌套事务执行


17、 Mybatis中的KaTeX parse error: Expected 'EOF', got '#' at position 2: 和#̲有啥区别,各自在什么场合使用。…是直接拼接;
#不需要关注数据类型,mybatis实现自动数据类型转换;KaTeX parse error: Expected 'EOF', got '#' at position 22: …转换,需要自行判断数据类型; #̲可以防止sql注入;不能防止sql注入;


18、 Mybatis的动态sql有哪些。


19、 简述redis的数据类型以及各自的应用场景。
类型:
String
应用场景:String是最常用的一种数据类型,普通的key/ value 存储都可以归为此类.即可以完全实现目前 Memcached 的功能,并且效率更高。还可以享受Redis的定时持久化,操作日志及 Replication等功能。
Hash
应用场景:在Memcached中,我们经常将一些结构化的信息打包成HashMap,在客户端序列化后存储为一个字符串的值,比如用户的昵称、年龄、性别、积分等,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。
List
应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。
Set:
应用场景:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
Sorted set
使用场景:
Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。


20、 简述redis的持久化,以及如何实现持久化
一:
Redis支持RDB和AOF两种持久化机制。持久化功能有效地避免因进程退出造成的数据丢失问题,下次重启时利用之前持久化的文件即可实现数据恢复。
RDB:RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。

二:1)执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如RDB/AOF子进程,如果存在bgsave命令直接返回。

? ? 2)父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞,通过info stats命令查看latest_fork_usec选项,可以获取最近一个fork操作的耗时,单位为微秒。

? ?3)父进程fork完成后,bgsave命令返回“Background saving started”信息并不再阻塞父进程,可以继续响应其他命令。

? ?4)子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行lastsave命令可以获取最后一次生成RDB的时间,对应info统计的rdb_last_save_time选项。

? ?5)进程发送信号给父进程表示完成,父进程更新统计信息,具体见info Persistence下的rdb_*相关选项。


21、 简述TCP、HTTP协议。 关于TCP/IP和HTTP协议的关系,网络有一段比较容易理解的介绍:“我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有很多,比如HTTP、FTP、TELNET等,也可以自己定义应用层协议。WEB使用HTTP协议作应用层协议,以封装HTTP 文本信息,然后使用TCP/IP做传输层协议将它发到网络上。”

术语TCP/IP代表传输控制协议/网际协议,指的是一系列协议。“IP”代表网际协议,TCP和UDP使用该协议从一个网络传送数据包到另一个网络。把IP想像成一种高速公路,它允许其它协议在上面行驶并找到到其它电脑的出口。TCP和UDP是高速公路上的“卡车”,它们携带的货物就是像HTTP,文件传输协议FTP这样的协议等。
你应该能理解,TCP和UDP是FTP,HTTP和SMTP之类使用的传输层协议。虽然TCP和UDP都是用来传输其他协议的,它们却有一个显著的不同:TCP提供有保证的数据传输,而UDP不提供。这意味着TCP有一个特殊的机制来确保数据安全的不出错的从一个端点传到另一个端点,而UDP不提供任何这样的保证。
HTTP(超文本传输协议)是利用TCP在两台电脑(通常是Web服务器和客户端)之间传输信息的协议。客户端使用Web浏览器发起HTTP请求给Web服务器,Web服务器发送被请求的信息给客户端。


22、 Nginx的作用
Nginx是一个轻量级、高性能、稳定性高、并发性好的HTTP和反向代理服务器。也是由于其的特性,其应用非常广。

反向代理,负载均衡,动静分离


23、 Mysql 数据库存储结构是什么?都有什么锁?

存储结构:B-tree索引 Hash索引
锁:行级锁(row-level),表级锁(table level),悲观锁(Pessimistic Lock),乐观锁(Optimistic Lock)


24、 Sql语句如何进行优化?

1 尽可能建立索引,包括条件列,连接列,外键列 等
2 尽可能让where中的列顺序与复合索引的列顺序一致
3 尽可能不要select *,而只列出自己需要的字段列表
4 尽可能减少子查询的层数
5 尽可能在子查询中进行数据筛选 …


25、 请简述支付宝的支付流程。
1.首先要到 蚂蚁金服开发者中心 注册商家账户,并认证。
2.下载java版的sdk和demo sdk&demo下载地址
3.将sdk加入到项目中,在项目根路径下新建libs文件夹,将jar包复制进去,我这里使用的是gradle,如果各位使用的是maven,请自行修改。
4.公钥、私钥的生成。生成公钥、私钥官方教程 ,按照官网教程操作,很简单的,这里就不上图片了。生成完之后将你的公钥要上传上去。
5.因为开发环境是使用沙箱环境,上线后会使用真实环境,所以支付宝的一些参数我们放到配置文件里
6.开始编写写接口 支付宝异步通知回调接口 这个接口的请求方式只能是post,如果用get会拿不到数据,不支持。 return url


26、 请写出springboot中几个常见的注解。
(1)@RestController和@Controller指定一个类,作为控制器的注解
(2)@RequestMapping方法级别的映射注解,这一个用过Spring MVC的小伙伴相信都很熟悉
(3)@EnableAutoConfiguration和@SpringBootApplication是类级别的注解,根据maven依赖的jar来自动猜测完成正确的spring的对应配置,只要引入了spring-boot-starter-web的依赖,默认会自动配置Spring MVC和tomcat容器
(4)@Configuration类级别的注解,一般这个注解,我们用来标识main方法所在的类
(5)@ComponentScan类级别的注解,自动扫描加载所有的Spring组件包括Bean注入,一般用在main方法所在的类上
(6)@ImportResource类级别注解,当我们必须使用一个xml的配置时,使用@ImportResource和@Configuration来标识这个文件资源的类。
(7)@Autowired注解,一般结合@ComponentScan注解,来自动注入一个Service或Dao级别的Bean
(8)@Component类级别注解,用来标识一个组件,比如我自定了一个filter,则需要此注解标识之后,Spring Boot才会正确识别。


27、 Springboot的核心配置文件有哪几个?它们的区别是什么?
Spring Boot 的核心配置文件是 application 和 bootstrap 配置文件。
application 配置文件这个容易理解,主要用于 Spring Boot 项目的自动化配置。
bootstrap 是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。
bootstrap 主要用于从额外的资源来加载配置信息,还可以在本地外部配置文件中解密属性。
这两个上下文共用一个环境,它是任何Spring应用程序的外部属性的来源。
bootstrap 里面的属性会优先加载,它们默认也不能被本地相同配置覆盖。
boostrap 由父 ApplicationContext 加载,比 applicaton 优先加载


28、 Springboot自动配置的原理是什么?

1)、SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration

2)、@EnableAutoConfiguration 作用:将 类路径下 META-INF/spring.factories 里面配置的所有

EnableAutoConfiguration的值加入到了容器中;

利用EnableAutoConfigurationImportSelector给容器中导入一些组件

可以查看selectImports()方法的内容;

List configurations = getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置 SpringFactoriesLoader.loadFactoryNames()
扫描所有jar包类路径下 META-INF/spring.factories
把扫描到的这些文件的内容包装成properties对象
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中​
每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;
3)、每一个自动配置类进行自动配置功能;


29、 在开发中都遇到了什么问题,你都是怎么解决的,都有什么收获?

开发问题:
线程问题,高并发问题,栈溢出等等
解决:
第一,百度查看解决方法。
第二,查看自己代码查看哪里写错了,过一下自己的思路和代码,看看是不是有问题。
第三,看JAVA帮助文档,看看自己的方法是否错误了。
第四,进群询问找人帮忙解答。
收获:
错过一遍的Bug,不会在错第二编,记在本子和记事本里


30、 现在公司给你一个需求,你拿到需求之后会做哪些事情,请简单阐述

根据需求进行分析如何实现,然后和同事交流,再去完成。


发布了2 篇原创文章 · 获赞 0 · 访问量 41

猜你喜欢

转载自blog.csdn.net/weixin_45724219/article/details/104794608