本文主要是介绍JAVA面试题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一、JAVA基础
1、什么是面向对象?
封装、继承、多态
2、对异常有什么看法?一般会如何做处理?(finally会用来做什么,关闭流的时候会放在哪个地方?)
- 异常是程序在编译或者运行的时候出现问题的显相;
- Throwable是所有Error(非程序问题,首要解决目标以及性能调优)和Exception(程序问题,且可处理可调式)的父类;
- 手动处理异常,可提升程序的健壮性;
3、JAVA中堆和栈的区别,说下java的内存机制。(引用类型能打印出来么?当打印一个String申明的变量时,打印出来的是什么?)
- 堆用于存放基本数据类型和对象的引用(引用类型的内存地址名)
- 栈专门用来存放引用数据类型的实际值,受JVM管理,开辟空间存放资源;
4、线程池的作用(简述单例模式的懒汉式跟饿汉式的优缺点)
5、垃圾回收机制的基本原理(不要讲太深,讲多了就是装13,容易被针对)
- 垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收;
- 当创建对象时,GC就开始监视这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理heap(堆)中的素有对象。通过这种方式确定哪些对象是“可达的”,哪些是“不可以达的”;
6、垃圾回收机制的优缺点
- 优点:最大的优点是不用程序员自己去管理内存;
- 缺点:“不用管”也意味着“失控”,所以GC提供了System.gc()、Runtime.gc()方法来通知GC回收;
7、lambada表达式的优缺点(JDK1.8)
- 优点:语法改进、语法简洁;
- 缺点:入门理解困难,不利于JAVA初学者理解;
8、HashMap是不是有序的
- HashMap 和 HashTable 都不是有序的;
- TreeMap和LinkedHashmap都是有序的(TreeMap默认是key升序,LinkedHashmap默认是数据插入顺序);
9、ArrayList和LinkedList的异同点
- 相同点:
- 不同点:
- ArrayList是Array(动态数组)的数据结构,LinkedList是Link(链表)的数据结构;
- 随机遍历访问时linkedlist的性能要低于arraylist;
- linkedlist的增删要优于arraylist;
- arraylist的初始化时默认10容量,而linkedlist默认初始化为空;
10、new ArrayList和Arrays.asList的区别
- Arrays.asList出来的长度是固定的;
- Arrays.asList 只支持遍历和取值,不支持 add(),remove()等任何修改操作,只能作为传递值的桥梁;
11、参数传递时,是按值传递还是引用传递;【这块我尚且存在争议,暂不写答案】
12、HashMap是如何解决hash冲突的(JDK1.8)
-
使用链地址法(使用散列表)来链接拥有相同hash值的数据;
-
使用2次扰动函数(hash函数)来降低哈希冲突的概率,使得数据分布更平均;
-
引入红黑树进一步降低遍历的时间复杂度,使得遍历更快;
二、中间件
1、消息队列有什么好处(用过哪些中间件,有没有遇到什么坑,举个例子)
- 提升系统响应速度;
- 生产和消费方解耦,让系统更健壮、稳定。
2、MQ消息丢失怎么办?
- 消息队列弄丢数据:持久化,非持久化的消息要及时处理,不要堆积(值得一提的是,持久化的情况下,最好要异步处理,且开启事务,不然会比较慢,数据量大的情况下容易导致连锁反应);
- 生产者弄丢数据:主流的MQ都有确认机制或者事务机制,可以保证生产者将消息送达到MQ。 比如RabbitMQ就有事务模式和confirm模式;
- 消费者弄丢数据:消费者丢数据一般是因为采用了自动确认消息模式。MQ收到确认消息后会删除消息,如果这时消费者异常了,那消息就没了。改用手动确认就能解决这个问题了;
3、MQ怎么达到顺序消费?
- 生产者保证顺序入队列,且入同一队列;
- 消费者保证消费的是一个队列,且避免多个消费者消费该队列的情况;
4、Redis用于缓存的好处,以及除了缓存外还有哪些应用场景
5、Redis中,分布式锁的原理是什么
- 分布式锁是为了解决分布式/集群服务应用场景下,明明不能被创建的对象,反而被不停创建——>消耗 的问题的(有点拗口,细细体会!);
- 简单来说,分布式锁能保证同一时间只能有一个客户端对共享资源进行操作;
- 分布式锁需要满足以下几点:
- 不会发生死锁(即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁);
- 具有容错性(只要大部分的Redis节点正常运行,客户端就可以加锁和解锁);
- 解铃还须系铃人(加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了);
- Redis提供的方法有:设置锁标志位、设置客户端唯一标识、提供锁过期时间;
- 看大神怎么玩转Redis 分布式锁的入口:https://blog.csdn.net/qq_37781649/article/details/108814474
6、如何解决Redis穿透(大致理解意思和明白解决方案便可,细究的话,需要结合实际应用来做具体分析)
- Redis穿透是指当请求到Redis中,没有命中Redis数据,进而到DB层去查询数据的一种现象;
- 解决方案:
- 若考虑黑客攻击的话,则需要结合布隆过滤器(BloomFilter)或者压缩filter提前拦截;
- 一般而言,定时从数据库查询数据存储到Redis中;
7、如何解决Redis雪崩
- Redis雪崩是指Redis数据由于某些原因被清空了,臂如Redis应用挂掉了、Redis缓存数据时间到期了,然后所有请求都走数据库的一种现象;
- 解决方案:
- 业务上加上判断,当redis取出的值为空时,则默认取什么值;
- 设置缓存数据的过期时间时,不用统一用一个值,可以在一定范围内进行随机,避免所有数据同一时间失效;
- 针对Redis挂掉的情况,可以采用事发前使用哨兵或集群模式,事发中设置本地缓存或限流,事发后自动重启并从磁盘中读取Redis数据,以求快速恢复缓存数据的三套策略;
三、主流框架技术
1、简述对spring的理解(最核心的是AOP和IOC,如果感觉面试时间较短,则可以发散讲讲 MVC 的理念)
- AOP:面向切面编程(主要是对某一个点进行拦截,然后在这个点之前或者之后执行某个公共方法,该公共方法具备可重用性)
- IOC:控制反转(利用注入依赖关系的方式,实现了各对象之间的解耦)
2、简述Spring Bean生命周期
- (开个玩笑,哈哈哈)主流程是:容器初始化——>业务调用——>关闭容器;
- 容器初始化的时候,依次会:构造Bean——>注入Bean属性——>(执行指定初始化方法),然后进行业务调用,最后销毁容器
3、依赖注入的方式
- 构造方法注入;
- setter注入;
- 基于注解的注入(官方推荐);
4、@RestController和@Controller的区别
- @RestController注解,相当于@Controller+@ResponseBody两个注解的结合
- 但使用@RestController这个注解,就不能返回jsp,html页面,视图解析器无法解析jsp,html页面
5、Spring Bean的作用域
- singleton:Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象(常用);
- prototype:每次通过Spring容器获取prototype定义的bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自己的属性和状态(常用);
- request:在一次Http请求中,容器会返回该Bean的同一实例。而对不同的Http请求则会产生新的Bean,而且该bean仅在当前Http Request内有效;
- session:在一次Http Session中,容器会返回该Bean的同一实例。而对不同的Session请求则会创建新的实例,该bean实例仅在当前Session内有效;
- global Session:在一个全局的Http Session中,容器会返回该Bean的同一个实例,仅在使用portlet context时有效;
6、Mybatis-plus 和 Mybatis 的区别(注意要结合项目阐述,不仅仅是以下几点区别)
- Mybatis-plus 是在 Mybatis 的基础之上做了更多的扩展;
- Plus能使用乐观锁;
- Plus具有代码生成器的功能;
- Plus可以进行 SQL 执行性能分析(不建议生产环境使用);
- Plus可以进行 SQL 执行分析拦截器(不建议生产环境使用);
7、resultType和resultMap的区别
- 总体而言,resultMap更强大,因为相比resultType而言,它能自由组合结果集;
- resultType是针对某一单个 VO 类进行一一映射;
- resultMap可以针对返回的结果集进行自由组合映射,不用再新建 VO 类,或者 PO类;
8、占位符#和$的区别
- #{} 只能表示某个值,后续填充的值与占位符是一一对应关系,较为单调,但不存在SQL注入风险;
- ${} 表示的是某个片段,可以进行任意填充,更灵活,但是存在SQL注入风险;
9、反射会花费更多的性能开销,但是Spring为什么用的那么爽
- 反射不会被JVM优化,确实会有更多的性能开销;
- Spring通过配置文件的形式把所有需要get和set的类全部在容器加载的时候就加入进去了;
- 通过二级缓存和三级缓存解决了循环依赖的问题(核心点);
10、Spring框架中运用了哪些设计模式(很多,以下挑几个典型的模式举例论证)
- 工厂模式:创建Bean对象,IOC就是工厂模式下建造出来的一个一个解耦的流水线;
- 单例模式:Spring Bean默认的作用域就是单例的;
- 代理模式:AOP的实现,就是代理模式,另外,经常使用的切面日志也是代理模式的体现;
- 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用;
- 装饰者模式:但凡你看见的每个空的实体父类,基本都是装饰者模式,不仅仅局限于Spring;
11、Dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,发布者和订阅者之间还能通信么?
- 可以通信的,启动dubbo时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用;注 册中心对等集群,任意一台宕机后,将会切换到另一台;注册中心全部宕机 后,服务的提供者和消费者仍能通过本地缓存通讯。服务提供者无状态, 任一台宕机后,不影响使用;服务提供者全部宕机,服务消费者会无法使用,并无限次重连等待服务者恢复;挂掉是不要紧的,但前提是你没有增加新的服务,如果你要调用新的服务,则是不能办到的;
12、Dubbo在安全机制方面是如何解决的
- Dubbo通过Token令牌防止用户绕过注册中心直连,然后在注册中心上管 理授权。Dubbo还提供服务黑白名单,来控制服务所允许的调用方。
13、SpringBoot 核心组件
- 【常用】Spring boot Starter(核心启动器、集成了很多常见依赖包)
- 【常用】Spring boot Autoconfigure(配置Bean到Spring容器中的代码实现包,这是Spring初期便有的一贯风格)
- Spring boot Cli(不常用,是一个客户端工具,结合了groovy脚本使用,有兴趣的可以了解下)
- Spring boot actuator(不常用,监控插件,有兴趣的可以了解下)
####四、数据库
五、其他
1、系统如何优化(有没有处理过系统性的问题,比如因线程问题导致的服务器宕机,或者因为没有借助缓存工具导致DB负荷较重而并发不够】
- 代码逻辑优化;
- 数据库优化;
- 借助第三方缓存工具,比如redis和mem的方式来提升读写,减轻DB压力;
- 服务器扩充,磁盘扩容等物理增大;
2、怎么解决高并发问题?(此问题不好回答,因为每个公司或者项目要求不一样,但主要从这几个方面来进行阐述)
- 服务层面(服务器扩容或单独服务器部署、数据库能力提升等);
- 代码层面(代码逻辑优化、第三方缓存提升读写、减少DB交互);
- 加锁(很多人能答出乐观锁,但是有时候从业务层面考虑的悲观锁更适用);
3、负载平衡的意义什么?
- 提升可用性(核心就是这一条,多说无益,但可以结合自身实战经验发散阐述);
4、tomcat调优(此处主要说几个参数便可,因为tomcat调优是和硬件相关的,有实战经验的可结合曾经的案例来发散回答)
- maxThreads:可创建的最大的线程数
- acceptCount:当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理;
- connnectionTimeout:网络连接超时时长,单位:毫秒。设置为0表示永不 超时,这样设置有隐患的。通常可设置为30000毫秒;
- minSpareThreadsTomcat:初始化时创建的线程数;
- maxSpareThreads:一旦创建的线程超过这个值,Tomcat就会关闭不再 需要的socket线程;
- minProcessors:最小空闲连接线程数,用于提高系统处理性能,默认值为10;
- maxProcessors:最大连接线程数,即:并发处理的最大请求数,默认值为75;
- acceptCount :允许的最大连接数,应大于等于maxProcessors,默认值为100;
- enableLookups 是否反查域名,取值为:true或false。为了提高处理能力,应设置为false;
- 增加tomcat内存(主要解决 OutOfMemoryError 问题);
这篇关于JAVA面试题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!