自己整理的在二线城市面试JAVA比较合理的题

180 阅读20分钟

初级

Spring的IoC理解:

(1)什么是IOC:

        IOC,Inversion of Control,控制反转,指将对象的控制权转移给Spring框架,由 Spring 来负责控制对象的生命周期(比如创建、销毁)和对象间的依赖关系。

        最直观的表达就是,以前创建对象的时机和主动权都是由自己把控的,如果在一个对象中使用另外的对象,就必须主动通过new指令去创建依赖对象,使用完后还需要销毁(比如Connection等),
				对象始终会和其他接口或类耦合起来。而 IOC 则是由专门的容器来帮忙创建对象,将所有的类都在 Spring 容器中登记,当需要某个对象时,不再需要自己主动去 new 了,只需告诉 Spring 容器,
				然后 Spring 就会在系统运行到适当的时机,把你想要的对象主动给你。也就是说,对于某个具体的对象而言,以前是由自己控制它所引用对象的生命周期,而在IOC中,所有的对象都被 Spring 控制,
				控制对象生命周期的不再是引用它的对象,而是Spring容器,由 Spring 容器帮我们创建、查找及注入依赖对象,而引用对象只是被动的接受依赖对象,所以这叫控制反转。

(2)什么是DI:

        IoC 的一个重点就是在程序运行时,动态的向某个对象提供它所需要的其他对象,这一点是通过DI(Dependency Injection,依赖注入)来实现的,即应用程序在运行时依赖 IoC 容器来动态注入对象所需要的外部依赖。
				而 Spring 的 DI 具体就是通过反射实现注入的,反射允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性

(3)IoC的原理:

        Spring 的 IoC 的实现原理就是工厂模式加反射机制,而在 Spring 容器中,Bean 对象如何注册到 IoC 容器,以及Bean对象的加载、实例化、初始化详细过程可以阅读这篇文章:

Spring AOP里面的几个名词的概念

1)连接点(Join point):指程序运行过程中所执行的方法。在Spring AOP中,一个连接点总代表一个方法的执行。 

(2)切面(Aspect):被抽取出来的公共模块,可以用来会横切多个对象。Aspect切面可以看成 Pointcut切点 和 Advice通知 的结合,一个切面可以由多个切点和通知组成。

在Spring AOP中,切面可以在类上使用 @AspectJ 注解来实现。

(3)切点(Pointcut):切点用于定义 要对哪些Join point进行拦截。

切点分为execution方式和annotation方式。execution方式可以用路径表达式指定对哪些方法拦截,比如指定拦截add*search*。annotation方式可以指定被哪些注解修饰的代码进行拦截。

(4)通知(Advice):指要在连接点(Join Point)上执行的动作,即增强的逻辑,比如权限校验和、日志记录等。通知有各种类型,包括Around、Before、After、After returning、After throwing。

(5)目标对象(Target):包含连接点的对象,也称作被通知(Advice)的对象。 由于Spring AOP是通过动态代理实现的,所以这个对象永远是一个代理对象。

(6)织入(Weaving):通过动态代理,在目标对象(Target)的方法(即连接点Join point)中执行增强逻辑(Advice)的过程。

(7)引入(Introduction):添加额外的方法或者字段到被通知的类。Spring允许引入新的接口(以及对应的实现)到任何被代理的对象。例如,你可以使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。

什么是事物?Spring当中的事物?什么时候失效?

spring mvc中的mvc?和spring boot有什么区别?我可以在springboot中用mvc吗?分别加哪些注解?

mybatis有哪些常用标签?

cache – 该命名空间的缓存配置。

cache-ref – 引用其它命名空间的缓存配置。

resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。

sql – 可被其它语句引用的可重用语句块。

insert – 映射插入语句。

update – 映射更新语句。

delete – 映射删除语句。

select – 映射查询语句。

@Component 和 @Bean 的区别/如何把一个对象放进spring容器中

作⽤对象不同: @Component 注解作⽤于类,⽽ @Bean 注解作⽤于⽅法;
@Component 通常是通过类路径扫描来⾃动侦测并⾃动装配到 Spring 容器中(我们可以使⽤ @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类⾃动装配到 Spring 的 bean 容器中)。
@Bean 注解通常是我们在标有该注解的⽅法中定义产⽣这个 bean,@Bean 告诉了Spring 这是某个类的示例,当我需要⽤它的时候还给我;
@Bean 注解⽐ Component 注解的⾃定义性更强,⽽且很多地⽅我们只能通过 @Bean 注解来注册 bean,⽐如当我们引⽤第三⽅库中的类需要装配到 Spring 容器时,则只能通过 @Bean 来实现。

Spring Cloud由什么组成?

Spring Cloud Eureka:服务注册与发现
Spring Cloud Zuul:服务网关
Spring Cloud Ribbon:客户端负载均衡
Spring Cloud Feign:声明性的Web服务客户端
Spring Cloud Hystrix:断路器
Spring Cloud Config:分布式统一配置管理

synchronized 和 Lock 有什么区别?

1、 首先synchronized是Java内置关键字,在JVM层面,Lock是个Java类;

2synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。

3synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不当没有 unLock()去释放锁就会造成死锁。

4、 通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。

LinkList和ArrayList有什么区别

String StringBuffer StringBuild

BIO、NIO有什么区别?

访问修饰符public、private、protected、以及不写(默认)时的区别?

Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
private : 在同一类内可见。使用对象:变量、方法。注意:不能修饰类(外部类)
public : 对所有类可见。使用对象:类、接口、变量、方法
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。注意:不能修饰类(外部类)。

HashMap底层

说下面向对象四大特性

封装、继承、多态、抽象。

实现线程的几中方式

继承 Thread 类

实现 Runnable 接口

实现 Callable 接口,需要实现的是 call() 方法

什么是事务?

事务是把一组密不可分的操作系列集合在一起,这些操作要么全部执行,要么全部不执行。

事务的四大特性(ACID)?

**原子性、一致性、隔离性、持久性**

对字符串类型的存储

说一下乐观锁和悲观锁?

数据库的乐观锁需要自己实现,在表里面添加一个 version 字段,每次修改成功值加 1,这样每次修改的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否一致,如果不一致就不修改,这样就实现了乐观锁。

删除语句?有什么区别?

删除表,包括表结构:DROP TABLE 表名称

删除数据库:DROP DATABASE 数据库名称

删除表内的数据,但并不删除表结构:TRUNCATE TABLE 表名称

表关联的几种方式?

数据库索引?

索引注意事项?

索引不会包含有NULL值的列
使用短索引
索引列排序
like语句操作
差异性较大

什么是RESTful API

RESTful风格的API接口:
1.通过HTTP GET/POST/PUT/DELETE 获取/新建/更新/删除 资源
2.一般使用JSON格式返回数据
3.一般web框架都有相应的插件支持RESTful API

中级

基础问题

exception和error区别

1ExceptionError都继承了Throwable类,在java中只有Throwable类型的实例才可以被抛出(Throw)或者捕捉(catch),它是异常处理机制的基本组成类型。Exception是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应的处理。

2Error指在正常情况下,不大可能出现的情况,绝大部门的Error都会导致程序处于非正常的,不可恢复状态。既然是非正常情况,所以不便于也不需要捕获。比如常见的OutOfMemoryError之类,都是Error的子类。

3Exception类又分为可检查异常(checked)和不检查异常(unchecked),可检查异常在源码里必须显示的进行捕获处理,这是编译期检查的一部分。不检查异常就是所谓的运行时异常,类似NullPointerException,ArrayIndexOutOfBoundsException之类,通常是可以编码避免的逻辑错误。

JVM内存结构

分区:
方法区: 类的信息
堆:对象的信息
程序计数器
JVM stacks 虚拟机栈 : 线程,局部变量,方法参数
Native Method Stacks本地方法栈
概览:
	线程私有
		1. 程序计数器
		2. 虚拟机栈
  线程共享
    1. 堆
    2. 方法区

JVM内存溢出

1、堆溢出

        绝大部分的内存溢出属于堆溢出,原因是大量对象占用了堆空间,而这些对象持有强引用,无法回收。-Xmx参数指定堆空间大小小于对象大小时候,溢出自然而然的就发生了。

    报错信息:java.lang.OutOfMemoryError: Java heap space
    为了减少堆溢出错误,一方面可以使用-Xmx指定一个更大的堆空间。另外可以通过MAT或者VisualVM等工具,找到大量占用堆空间的对象,并在代码上合理优化。

2、直接内存溢出

        在Java的NIO中,支持直接内存使用,也就是通过Java代码获取一块堆外内存,该内存是直接向操作系统申请的。直接内存申请速一般比堆内存慢,但是访问速度快于堆内存,因此对于那些可以复用经常访问的空间,
				使用直接内存可以提高系统的性能,但是由于该内存没有JVM托管,使用不当容易触发直接内存溢出,导致宕机。

        -XX:+PrintGCDetails 输出GC详情

        报错信息:java.lang.OutOfMemoryError: Direct buffer memory

        直接内存不一定触发GC,触发直接内存使用量达到-XX:MaxDirectMemorySize的设置值。所以保证内存不溢出就需要合理的进行FullGC。或者设订一个系统可达的-XX:MaxDirectMemorySize值。
				通过显示的gc是可以回收直接内存的。

        在不使用-XX:MaxDirectMemorySize设置最大最直接内存空间的时候,默认情况最大可用直接内存等于-Xmx即堆空间的大小。 

        避免直接内存溢出:

                1、合理的GC

                2、设置系统容许的-XX:MaxDirectMemorySize

                3、设置小的-Xmx
3、过多线程导致OOM

       线程的栈空间也是在堆外分配的,和直接内存非常相似,如果想让系统支持更多的线程,那么应该使用一个较小德尔堆空间。 

        报错信息: unable to create new native thread

        原因是Java进程达到了可使用的内存上限。减少堆空间,减少线程占用的占空间使用-Xss参数可以指定线程的栈空间。

        -Xmx1g -Xss128k 堆空间还是1g,但是线程栈空间减少到128k,剩余的可用内存里可以容纳更多的线程。

4、MetaspaceOOM

      Metaspace元空间主要存储类的元数据信息,例如:类型、属性、方法、访问限制等。可见Metaspace空间增长是由于反射类加载、动态代理生成的类加载等导致的,也就是说Metaspace的大小和加载的数据有关,加载的类越多metaspace占用的内存也就越大。

        -XX:+TraceClassLoading -XX:+TraceClassUnloading可以记录类加载和卸载的情况。

5、GC效率低导致OOM

      GC 是内存回收的关键,如果GC效率地下,那么系统的性能会收到严重的影响。如果堆空间太大,GC所花费的时间就会较多,并且回收释放的对象较少,虚拟机认为GC效率地下的可能抛出OOM,
     当遇到一下情况时候,抛出GC overhead limit exceeded.

        1、花费在GC上的时间超过98%

        2、老年代释放内存是否小于2%

        3、eden区释放内存是否小于2%

        4、是否连续5次同时出现上述case。

Spring Bean的生命周期?

简单来说,Spring Bean的生命周期只有四个阶段:实例化 Instantiation --> 属性赋值 Populate  --> 初始化 Initialization  --> 销毁 Destruction

**Spring Cloud 和dubbo区别?

1)服务调用方式:dubbo是RPC springcloud Rest Api
(2)注册中心:dubbo 是zookeeper springcloud是eureka,也可以是zookeeper
(3)服务网关,dubbo本身没有实现,只能通过其他第三方技术整合,springcloud有Zuul路由网关,作为路由服务器,进行消费者的请求分发,springcloud支持断路器,与git完美集成配置文件支持版本控制,事物总线实现配置文件的更新与服务自动装配等等一系列的微服务架构要素

SpringBoot和springcloud认识

1、 SpringBoot 是 Spring 的⼀套快速配置脚⼿架,可以基于SpringBoot 快速开发单个微服务,Spring Cloud是⼀个基于SpringBoot实现的云应⽤开发⼯具;

2、 SpringBoot专注于快速、⽅便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;

3、 SpringBoot使⽤了默认⼤于配置的理念,很多集成⽅案已经帮你选择好了,能不配置就不配置;

4、 Spring Cloud很⼤的⼀部分是基于SpringBoot来实现,可以不基于SpringBoot吗?不可以。

为何CAP无法同时满足

1)当前满足CA,能否也满足P?
假设当前分布式系统满足CA,C要求各个客户端读到的数据必须是一致的,考虑发生网络分区的情况,这个时候各个服务器存在数据不一致,那么根据C一致性要求,系统是不可以对外提供服务的(因为不同的客户端访问同一份数据会得到不同的结果),那么也就违背了分区容错性P。

(2)当前满足CP,能否也满足A?
假设当前分布式系统满足CP, 在网络发生分区的情况下,为达到C一致性, 请求只能一直等待,等待网络分区情况解除,系统数据同步完成才能返回,这就无法满足可用性A。

(3)当前满足AP,能否也满足C?
假设当前分布式系统满足AP, 系统要求在一定的时间内就要返回,在发生网络分区的情况下,为了保证P,即使出现网络分区也要正常提供服务,按时返回数据,可这样不同客户端访问同一份数据会得到不同的结果,这就不能保证数据的一致性C。

总结:

(1)分布式环境下的CAP理论无法同时满足,一般根据业务需要满足其中两个
(2)一些分布式一致性服务,比如zookeeper,牺牲一致性来保证集群的稳定性和可用性,它们无法做到强一致性,但是可以达到最终一致性。

网关的作用是什么

统一管理微服务请求,权限控制、负载均衡、路由转发、监控、安全控制黑名单和白名单等

高级

高级问题

⽐较⼀下充⾎模型和贫⾎模型的优缺点,在医院单体服务的情况下,应该使⽤什么样的模型,为什么?

贫血模型:
需要User+UserService,
添加新用户userService.save(User user)。
充血模型:
user.save()
期望的回答:贫⾎模型是不包括业务逻辑的,充⾎模型是包括业务逻辑的。贫⾎模型不够⾯向对象,领域对象只是⽤来做信号传递,充⾎模型的业务逻辑划分通常存在⽐较含糊的情况。(然后了解⼀下他为什么这部分有什么⻅解

后台服务出现明显“变慢”,谈谈你的诊断思路?

期望的回答:不武断地直接从sql优化说起,⽽是先谈谈慢的概念,观察哪些内容,前期的情况,之后的情况,然
后再针对各种可能的情况做出⼀定的诊断思路。

数据库的读写分离和分库分表是怎么做的?

读写分离:
	部署多台数据库,选择一种的一台作为主数据库,其他的一台或者多台作为从数据库。
	证主数据库和从数据库之间的数据是实时同步的,这个过程也就是我们常说的主从复制。
	系统将写请求交给主数据库处理,读请求交给从数据库处理。
	可以在应用和数据中间加了一个代理层。应用程序所有的数据请求都交给代理层处理,代理层负责分离读写请求,将它们路由到对应的数据库中。

如何分表:
	根据行业惯例,通常按照 水平切分、垂直切分 两种方式进行切分,当然,有些复杂业务场景也可能选择两者结合的方式。

(1)水平切分
	这是一种横向按业务维度切分的方式,比如常见的按会员维度切分,根据一定的规则把不同的会员相关的数据散落在不同的库表中。
  由于我们的业务场景决定都是从会员视角进行数据读写,所以,我们就选择按照水平方式进行数据库切分。

(2)垂直切分
	垂直切分可以简单理解为,把一张表的不同字段拆分到不同的表中。
	比如:假设有个小型电商业务,把一个订单相关的商品信息、买卖家信息、支付信息都放在一张大表里。可以考虑通过垂直切分的方式,把商品信息、买家信息、卖家信息、支付信息都单独拆分成独立的表,
  并通过订单号跟订单基本信息关联起来。
	也有一种情况,如果一张表有10个字段,其中只有3个字段需要频繁修改,那么就可以考虑把这3个字段拆分到子表。避免在修改这3个数据时,影响到其余7个字段的查询行锁定。

什么情况下需要分库分表?
	单表的数据达到千万级别以上,数据库读写速度比较缓慢(分表)。
	数据库中的数据占用的空间越来越大,备份时间越来越长(分库)。

分库分表会带来什么问题呢?
	join 操作 : 同一个数据库中的表分布在了不同的数据库中,导致无法使用 join 操作。
	事务问题 :同一个数据库中的表分布在了不同的数据库中,如果单个操作涉及到多个数据库,那么数据库自带的事务就无法满足我们的要求了。
	分布式 id :分库之后, 数据遍布在不同服务器上的数据库,数据库的自增主键已经没办法满足生成的主键唯一了。我们如何为不同的数据节点生成全局唯一主键呢?这个时候,我们就需要为我们的系统引入分布式 id 了。

架构类问题

CAP是什么

1)一致性C:

   单机环境下, 数据只有一份,所有的客户端访问的是同一份数据,不会出现两个客户端看到不一样的数据;
   分布式环境下,同一份数据会保存在多台服务器上,大量客户端来访问数据,负载会分布在各个服务器上,两个不同的客户端C1,C2可能访问的是不同的两台服务器S1,S2, 如果S1,S2上当前数据完全一样,C1,C2会拿到同样的数据,满足一致性;
   而要保证每个时刻S1,S2上的数据完全一样,在每次对数据更新的时候,就必须等待C1,C2都完成了数据更新, 该次数据更新操作才能成功返回。

(2)可用性A:

 可用性要求所有的读写请求必须在一定的时间得到响应,可以终止,但是不可以一直等待。
 在单机环境中,如果服务没问题,读写服务可以很快返回,如果服务器挂掉,也可以很容易做到返回响应。
 但是在分布式环境中,一个写请求达到某一个服务器,该服务更新数据后还得和集群中其他服务器同步数据,保证各个服务器数据一致, 但是网络是不可控的,可能某些服务器之间的网络出现故障,或者其他的各类原因导致更新请求无法送达,或者更新完成ACK无法返回,这个时候就要选择是直接返回,还是等待更新成功。

(3)分区容错性P:

分区容错性要求在发生网络分区的情况下,被分割的节点仍能对外提供服务。
单机环境下不会发生网络分区,分布式环境下,任意时刻,当前环境下各个服务器的数据即使存在不一致,也要系统能正常对外提供服务。
这就会导致一个问题,多个客户端访问不同的服务器,由于数据不一致,会存在对同一份数据的访问,得到不同的结果(也就是违背了一致性原则

为何CAP无法同时满足

1)当前满足CA,能否也满足P?
假设当前分布式系统满足CA,C要求各个客户端读到的数据必须是一致的,考虑发生网络分区的情况,这个时候各个服务器存在数据不一致,那么根据C一致性要求,系统是不可以对外提供服务的(因为不同的客户端访问同一份数据会得到不同的结果),那么也就违背了分区容错性P。

(2)当前满足CP,能否也满足A?
假设当前分布式系统满足CP, 在网络发生分区的情况下,为达到C一致性, 请求只能一直等待,等待网络分区情况解除,系统数据同步完成才能返回,这就无法满足可用性A。

(3)当前满足AP,能否也满足C?
假设当前分布式系统满足AP, 系统要求在一定的时间内就要返回,在发生网络分区的情况下,为了保证P,即使出现网络分区也要正常提供服务,按时返回数据,可这样不同客户端访问同一份数据会得到不同的结果,这就不能保证数据的一致性C。

总结:

(1)分布式环境下的CAP理论无法同时满足,一般根据业务需要满足其中两个
(2)一些分布式一致性服务,比如zookeeper,牺牲一致性来保证集群的稳定性和可用性,它们无法做到强一致性,但是可以达到最终一致性。