欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java综合面试题(更新ing)

程序员文章站 2024-01-11 15:20:16
...

一、项目

1.1.知道你的项目到底是做什么的,有哪些功能。

1.2.知道你做的模块在整个项目中所处的位置及作用,并能清晰的阐述模块间的调用关系。

1.3.知道你项目的整体架构和使用到的中间件,并对中间件的原理有一定的了解。

1.4.能流畅阐述的自己在项目中解决过的比较复杂的问题(重点)。

1.5.自我介绍

二、Java基础知识

2.1.栈和队列的区别

2.2.接口和抽象类的区别

首先,接口和抽象类的共同点是都不可以直接实例化,接口和抽象类的实现类只有实现了两者中的方法才能进行实例化。

接口是公开的,不能有私有的方法或变量,接口中的所有方法都没有方法体,通过关键字interface实现。Java1.8之后,接口中default的方法也可拥有方法体了。

抽象类是可以有私有方法或私有变量的,通过把类或者类中的方法声明为abstract来表示一个类是抽象类,被声明为抽象的方法不能包含方法体

实现接口的关键字为implements,继承抽象类的关键字为extends。Java中是单继承、多实现模式。

接口强调特定功能的实现,而抽象类强调所属关系。接口被用于常用的功能,便于日后维护和添加删除,而抽象类更倾向于充当公共类的角色,不适用于日后重新对立面的代码修改。功能需要累积时用抽象类,不需要累积时用接口。

2.3.int和Integer的区别,以及自动拆箱/装箱的相关问题

int是我们常说的整形数字,是基本类型,Java的原始数据类型之一。

Integer是int对应的包装类,是引用类型,它有一个int类型的字段存储数据,并且提供了基本操作,比如数学运算、int和字符串之间转换等。

在Java1. 5中,引入了自动装箱和自动拆箱功能(boxing/unboxing),Java可以根据上下文,自动进行int和Integer类型转换,极大地简化了相关编程。

在int到Integer的自动装箱操作中,会调用Integer的静态工厂方法**valueOf(int i)**方法,在调用它的时候会利用一个缓存机制,带来了明显的性能改进。Integer中有一个IntegerCache内部类,valueOf()方法先判断了变量i的值是否在这个缓存范围内,也就是[-128,127],在这个范围内直接返回创建好的对象,并不会重新创建对象。

JVM调优:IntegerCache缓存类的上下限,下限不可以配置,上限可以通过JVM参数进行配置。调高后可以避免创建更多的Integer对象节省内存。

valueOf()方法:

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

IntegerCache内部类:

    private static class IntegerCache {
        //下限-128
        static final int low = -128;
        static final int high;
        static final Integer cache[];
        static {
            // 默认上限127
            int h = 127;
            // JVM参数中若设置了上限,则以JVM参数为上限
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
		...
		}

JVM参数:-XX:AutoBoxCacheMax=20000 //Intger缓存池上限设置为20000

2.4.常量池相关问题

2.5.==和equals的区别

2.6.重载和重写的区别

2.7.String、StringBuilder、StringBuffer的区别

三、集合框架

3.1.ArrayList、LinkedList、HashMap、LinkedHashMap、ConcurrentHashMap的底层实现原理。

3.2.JDK1.7版本和1.8版本的HashMap的区别。

3.3.JDK1.7版本和1.8版本的ConcurrentHashMap的区别。

3.4.HashMap能不能排序?HashMap的长度为什么要是2的幂次方?

HashMap是根据hash算法计算的存放下标,所以是无序的。可以依靠一些有序的集合来进行排序。

  • 把每一个HashMap的键值对作为一个Entry 存入到ArrayList里. 然后对ArrayList进行排序.
  • 在Java8中还可以对HashMap的EntrySet进行流式处理,直接对EntrySet调用sorted方法,定义排序逻辑,然后再遍历使用。

Map还提供了一些有顺序的Map框架,比如TreeMap,按照键值的自然规则进行排序,也可以在初始化的时候传入比较器,自定义排序规则。还有LinkedHashMap,根据放入元素的顺序依次放入map中。

为什么是2的幂次方?

  • 当长度为2的n次方时,hash值对数组长度取模等于(n-1)& hash,而做与运算要比取模速度快,因为与运算是位运算,计算机直接在内存中操作,避免了进制的类型转换。
  • 当长度为2的n次方时,n-1转换二进制末尾的位数全都是1,因为在计算下标时(n-1)& hash做的是与运算,与运算中只要是0结果就为0,而增加1的比重可以降低相同下标结果的产生,降低hash冲突。

四、多线程

4.1.创建线程的几种方式?wait、sleep分别是谁的方法?区别?线程间的通信方式?

4.2.介绍下什么是死锁,遇见过死锁吗?你是怎么排查的。(可以通过jps排查)

4.3.创建线程池的几种方式,线程池有什么好处。

4.4.线程继承和接口的区别,接口有什么好处。

4.5.synchronized、Lock、ReentrantLock的区别,用法及原理。

4.6.CountDownLatch与CyclicBarrier用法

4.7.ThreadLocal的用法和原理

4.8.volatile关键字的作用和原理

4.9.乐观锁和悲观锁

4.10.对公平锁、非公平锁、可重入锁、自旋锁、读写锁的理解

4.11.CAS是什么及底层原理。

4.12.ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等等堵塞队列的理解

4.13.ThreadPoolExecutor的传入参数及内部工作原理

4.14.给你一个具体的业务场景,让你使用ThreadPoolExecutor创建一个适合的线程池。

4.15.分布式环境下,怎么保证线程安全。

五、JVM相关问题

5.1.JVM内存机制

5.2.介绍下垃圾收集机制,垃圾收集有哪些算法,各自的特点。

5.3.聊聊GC,谈谈MajorGC、FullGc的区别,垃圾收集器有哪些,他们的区别?

5.4.OutOfMemoryError这个错误你遇到过吗?你是怎么解决处理的?

5.5.JVM调优有哪些参数,介绍下,线上环境上,你是怎么查看JVM的参数并进行调优的?

5.6.能不能自己写一个类叫java.lang.String(类加载的过程,双亲委派模型)

六、框架相关问题

6.1.Spring用了哪些设计模式? Spring注入bean的方式?对SpringIOC和SpringAOP的理解?

1.代理模式: AOP 就是基于动态代理的,如果有AOP设置的切面拦截的对象,Spring框架会调用jdk动态代理或者cglib创建对应的代理对象,然后存到ioc容器。调用对象的方法时实际上就是调用代理对象的invoke方法,实现对方法的增强或扩展。

适配器模式: 在Spring MVC中,DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。解析到对应的 Handler后,开始由HandlerAdapter 适配器处理。HandlerAdapter 作为期望接口,具体的适配器实现类用于对目标Handler进行适配。

为什么要在 Spring MVC 中使用适配器模式? Spring MVC 中的 Handler类型众多,比如最早期的mvc框架可以直接实现Controller接口来注册一个Handler方法,也有实现Servlet接口和添加Controller注解等不同方式。不同类型的 Handler通过不同的方法来对请求进行处理。

BeanFactory 简单工厂模式;singleton 单例模式

2. 一、构造器注入;二、设值注入(setter方式注入);三、Feild方式注入(注解方式注入)。

3.IoC Inversion of Control (控制反转/反转控制):是⼀个技术思想,不是⼀个技术实现
描述的事情:Java开发领域对象的创建,管理的问题
传统开发⽅式:⽐如类A依赖于类B,往往会在类A中new⼀个B的对象
IoC思想下开发⽅式:我们不⽤⾃⼰去new对象了,⽽是由IoC容器(Spring框架)去帮助我们实例化对
象并且管理它,我们需要使⽤哪个对象,去问IoC容器要即可
我们丧失了⼀个权利(创建、管理对象的权利),得到了⼀个福利(不⽤考虑对象的创建、管理等⼀系列
事情)
为什么叫做控制反转?
控制:指的是对象创建(实例化、管理)的权利
反转:控制权交给外部环境了(spring框架、IoC容器)

aop: aop实际是对oop面向对象编程的扩展,面向对象编程在各个对象顺序执行时会产生横切逻辑代码即重复代码,比如事务控制、权限校验等。aop思想强调的是将横切逻辑代码和业务逻辑代码分离,将横切逻辑代码进行单独抽取去影响到需要执行的方法中,每一个被影响的方法为一个点,多个点构成面,这就是aop中所说的面向切面编程。

6.2.Spring事务隔离级别和传播机制

一个完整的事务必须满足它的四大特性(ACID):

  • 原子性:在一个事务中的操作都是一个逻辑的单元,在执行事务序列时,这些操作要么全部成功,要么全部失败。
  • 一致性:对于事务操作,其始终能够保证在事务操作成功或者失败回滚时能够达到一种一致的状态。
  • 隔离性:各个事务之间的执行是相互不影响。
  • 持久性:事务的持久性指的是事务一旦执行成功,那么其所做的修改将永久的保存在数据库中,此时即使数据库崩溃,修改的数据也不会丢失。

隔离级别问题:

  • 脏读:(读未提交的内容 导致)

    表示一个事务能够读取另一个事务中还未提交的数据。比如,A事务增删改查数据,尚未提交,B事务可以读到A事务尚未提交的这些数据。

  • 幻读:(主要针对insert、delete操作,解决需要锁住整表)

    A事务根据查询条件或得N条数据,B事务删除N条中的M条,或增加M条符合查询条件的M条数据后提交,事务A再进行查询得到了N ±M条数据,像产生了幻觉。

  • 不可重复读:(主要针对update操作,解决需要加上行锁)

    A事务读到某条数据的值后,B事务对此条数据进行修改后提交,A事务再次读这条数据读到了不同的值。两次重复读的值不同,即不可重复读。

Spring事务隔离级别:(ISOLATION)就是以上问题的解决方案

  • DEFAULT:默认隔离级别,每种数据库支持的事务隔离级别不一样,Oracle默认(读已提交) Mysql默认(可重复读)。
  • READ_UNCOMMITTED:读未提交,即能够读取到没有被提交的数据,这是隔离性最低的一种隔离级别,无法解决脏读、不可重复读、幻读问题。
  • READ_COMMITED:读已提交,即能够读到那些已经提交的数据,能够防止脏读,避免不了幻读和不可重复读。
  • REPEATABLE_READ:可重复读,解决脏读和不可重复读的问题,但是其无法解决幻读。
  • SERLALIZABLE:串行化,提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,故此性能很低

Spring传播级别:(PROPAGATION)方法调用方法如何传播,七种级别,常用两种

  • REQUIRED:Spring默认,支持当前事务,如果当前没有事务,就新建一个事务。
  • SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。

6.3.Mybatis的缓存机制(一级缓存和二级缓存),Mybatis的mapper文件中#和$的区别

一级缓存

一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HahsMap)是互相不影响的。

二级缓存

二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。每一个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。

#为占位符,$为拼接符

#为参数占位符,相当于JDBC中PreparedStatement,使用提前占位的方式进行参数注入,变量替换后会自动加上单引号。$ 为字符串替换,相当于JDBC中的普通的Statemetn,变量是直接以字符串拼接的方式替换参数,所以 $ 这种方式可能会导致sql注入的问题。工作中一般使用#号。

6.4.SpringMVC的请求的处理流程

Java综合面试题(更新ing)

6.5.什么是MVC模式?SpringMVC?

首先要清楚三层架构:表现层、业务层、持久层

  • 表现层:即web层,包括了展示层(前端)和控制层(Controller)

    ​ 负责接收客户端请求,向客户端响应结果。表现层的设计一般使用MVC模式。(即MVC是表现层的模式,和其它层无关)

  • 业务层service层。

    ​ 业务逻辑处理,事务控制。表现层依赖业务层,业务层不依赖表现层。

  • 持久层dao

    ​ 负责数据持久化。

MVC设计模式

  • Model:模型,包括业务模型和数据模型。数据模型用来封装数据,业务模型用于处理业务。
  • View:视图,展示数据。
  • Controller:控制器,应用程序处理用户交互的部分,一般用来处理程序逻辑。

MVC模式是为了解决代码耦合,提倡分层架构,每层只维护自己层的代码,降低代码之间的耦合,增加代码的可维护性。

SpringMVC和Struts2一样都是基于MVC设计模式的,为了解决表现层问题的web框架。本质可以认为是对servlet的封装,简化对servlet的开发。
Java综合面试题(更新ing)
与Spring的联系:并无绝对关联关系,一般配合使用。Spring致力解决对象之间耦合关系,ioc容器思想贯穿整个全局环境,SpringMVC主要作用在表现层,也可将对象交于Spring的ioc容器中进行管理。所以也称Spring和SpringMVC为父子容器。

6.5.Spring和SpringBoot的区别?

Spring框架为开发Java应用程序提供了全面的基础架构支持。它包含一些很好的功能,如依赖注入和开箱即用的模块,如:Spring JDBC 、Spring MVC 、Spring Security、 Spring AOP 、Spring ORM 、Spring Test,这些模块缩短应用程序的开发时间,提高了应用开发的效率。

众所周知Spring框架需要进行大量的配置,Spring Boot引入自动配置的概念,让项目设置变得很容易。Spring Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。Spring Boot实现了自动配置,降低了项目搭建的复杂度。

6.6.RPC框架有哪些,他们的区别?

6.7.Dubbo的使用和理解

6.8.SpringCloud的使用和组件,谈谈你的理解

七、消息中间件

7.1.你们公司是如何进行消息中间件的技术选型?

7.2.如何保证消息中间件的高可用?

7.3.如何保证消息中间件重复发送消息?

7.4.消息队列积压了大量的消息,你该怎么处理?

7.5.如何保证消费者消费消息是有顺序的?

7.6.让你来开发一个消息中间件,你会怎么架构?

八、Redis

8.1.你们公司为什么要使用Redis?Redis有几种数据类型?

8.2.Redis持久化机制?Redis的过期策略?

8.3.怎么保证Redis的高可用?

8.4.什么是缓存穿透?如何避免?什么是缓存雪崩?如何避免?

8.5.如何保证缓存与数据库的双写一致性?

8.6.Redis单线程模型原理,为什么能支撑高并发?

8.7.Redis哨兵架构的理解和底层原理。

九、数据库

9.1.工作中你是怎么优化sql的?

sql优化的重点在于sql语句对索引的正确使用,我们在开发中常见的错误是对数据库表进行全盘扫描,从而影响性能,耗费时间。 所以对sql优化的基础就是避免全盘扫描数据库表。

9.2.什么情况下,索引会失效?

  • 1.where条件中有or;
  • 2.复合索引未用左列字段;
  • 3.like以%开头;
  • 4.需要类型转换;
  • 5.where中索引列有运算;
  • 6.where中索引列使用了函数;
  • 7.如果mysql觉得全表扫描更快时(数据少);

9.3.数据库的存储存储引擎,比如:MySQL的MyISAM和InnoDB区别?

  • InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

  • InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;

  • InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。

  • InnoDB支持表、行(默认)级锁,而MyISAM支持表级锁

    InnoDB为什么推荐使用自增ID作为主键?

    答:自增ID可以保证每次插入时B+索引是从右边扩展的,可以避免B+树和频繁合并和分裂(对比使用UUID)。如果使用字符串主键和随机主键,会使得数据随机插入,效率比较差。

9.4.索引的最左原则

9.5.索引的底层原理

9.6.你们公司是怎么进行分库分表?分库分表的方案(主从库,Mycat)

十、其他

10.1.分布式事务是怎么解决的?

10.2.分布式session方案?

10.3.设计一个秒杀场景。

10.4.怎么防止表单多次提交?

10.5.Linux的基本操作命令

10.6.ElasticSearch的使用和原理

10.7.Zookeep的使用和原理

十一、HR面试

11.1.简历中写的过去工作经历的离职原因

11.2.当前公司薪资待遇

11.3.期望能到怎样的一家公司

11.4.个人未来的发展方向