2021Java面试题附答案(持续更新)

整体准备内容:,希望面试能过!!!!


Java基础核心

 1.String a = "123"; String b = "123";String c=new String("123"); a==b的结果是什么?  a==c的结果?  

 答:true,false。a==b指向常量池中的同一个地址。a==c ,由于c是在堆中的对象,而a是常量池中的对象,因此是不同地址。

具体:https://blog.csdn.net/x18094/article/details/113873202

2.==和equals的区别?  

答: ==比较的是对象的引用地址,equals比较的是对象内容。

3.||和&&的优先级哪个高?  

 答:或的优先级高,true || true && false,  先计算或 ,再计算true && false

4.ArrayList和LinkedList底层实现有什么差别? 

答:   arraylist底层是数组,linkedlist底层是链表。需要保持输入输出顺序时要linkedlist

5.volatile关键字有什么作用?

   答: 保证有序性和内存可见性。多线程下需要及时更新值到主存时使用。

6.Java的静态代理和动态代理有什么差别?

答: 静态代理编译前就写好代理类,动态代理则是利用反射在运行时动态生成代理类。

7.String和StringBuffer、StringBuilder有什么区别? 

   答:String是不可变的,StringBuffer和StringBuilder是可变的。StringBuffer是线程安全的,StringBuilder是不安全的。

扫描二维码关注公众号,回复: 12627437 查看本文章

8.HashMap的底层结构是什么?  

 答:数组+链表+红黑树

9.HashMap的Put()方法原理?  

 答:(1)调用 hash(Key) 方法计算 Key 的 hash 值,再计算得到数组下标。
(2)若key的hash在HashMap中不存在,则插入,若已经存在,发生碰撞。
 (3)当发生碰撞时(两个不同的字符串key可能计算出的hash相同)
         若key相等,则更新Value。
         若key不想等,则加到链表的尾部。
  (4)如果放链表时发现当链表长度大于8,且数组长度大于64,把键值对放红黑树(链表转红黑树)。


10.HashMap里的hashcode方法和equal方法什么时候需要重写?

    答:对象作为hashmap的key时要重写equals方法,不写equals会不相等。

11.hashmap扩容机制是什么?  

 答:jdk1.8初始是0,put的时候扩容成16,加载因子默认0.75, 当达到容量的0.75的时候就要扩容,扩容成2倍。

12.hashmap为什么使用红黑树?为什么不直接使用红黑树?  

 答:数组太长插入慢,链表太长查询慢,二叉树树太高,红黑树通过左旋、右旋变色来平衡二叉树。如果树很短,没必要使用红黑树,因为平衡二叉树也需要消耗,反而更慢。

13.jdk8中对HashMap做了哪些改变?

    答:jdk1.8引入了红黑树;hash碰撞时,jdk1.8从链表的尾部插入,而1.7是头插法。


14.ConcurrentHashMap怎么实现线程安全?

    答:JDK 1.7 中采用 分段锁的方式;JDK 1.8 中直接采用了CAS(无锁算法)+ synchronized。

class.forName()和classLoader都可用来对类进行加载,它们的区别?    

答:Class.forName得到的class是已经初始化完成的
Classloder.loaderClass得到的class是还没有链接的。
class.forName()前者除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。
而classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。
Class.forName(name, initialize, loader)带参函数也可控制是否加载static块。"

类实例化执行顺序?

答:父子类静态代码块  static{...}--->main方法----->父子非静态代码块 {...}------>构造函数 ------->一般方法

访问修饰符的作用域?

答:口诀:类包子非,一二三四。  private(1)-default(2)-protected(3)-public(4) ,数字代表几个√

深拷贝和浅拷贝区别?

答:深拷贝会拷贝对象里的引用,比如属性是一个其他对象。浅拷贝不会拷贝属性对象,只是复制了地址。

什么是序列化和反序列化?

答:序列化:对象--》字节;反序列化:字节--》对象
 


Spring

1.restcontroller 和controller有什么区别?

答:restcontroller=controller+@resposebody

2.controller是单例的吗?

答: 默认是的。scope可设置成多例,作用域:singleton(单例)、prototype(多例)

3.过滤器拦截器有什么区别?

答:过滤器依赖servlet容器,基于函数回调实现,在容器初始化时调用一次,几乎可以过滤所有资源包括静态文件。拦截器基于web框架比如springmvc,基于反射实现运用aop,可以多次调用,但只能拦截controller,无法拦截静态文件。


4.spring bean的生命周期?

答:加载bean定义、bean工厂处理器实例化、属性赋值、aware接口扩展beanpost前置处理器初始化beanpost后置处理器-bean的使用销毁


5.spring bean的初始化怎么做?

答:1.配置init-method @Bean(init-method="xx") 2.实现InitializingBean方法afterPropertiesSet,3。加@PostConstruct 顺序:postConstruct>afterPropertiesSet>init-method


6.简单说下IOC和AOP?

答:ioc就是权限控制反转,创建对象交给spring容器来做,便于管理。aop就是面向切面编程,它通过动态代理为spring对象增加功能。比如增加日志切面,spirng的事务以及拦截器都是运用了aop。


7.spring的动态代理用哪种实现?

答:spring默认是采用jdk的动态代理,如果想要用cglib可以通过配置文件的方式指定。


8.jdk代理和cglib代理有什么区别?

答:jdk代理利用反射对实现接口的类生成代理,而cglib则利用字节码技术生成一个子类。前者必须是有实现接口才可以,后者则是生成子类,因此目标类不能是final的。


9.spring依赖注入方式有几种,分别是什么?

答:常见的有3种。构造器注入、set方法注入、属性注入(autowire或者resorce)、接口注入(不常用)


10.springmvc流程?

答:面试回答-->(前端控制器(DS)接收请求,然后DS调用处理器映射器HandleMapping,生成处理器对象和拦截器,DS再调用处理器适配器HandleAdapter找到对应的handle,调用handler返回模型视图,DS调用视图解析器解析视图,最后浏览器渲染给用户。)

核心组件:
前端控制器 DispacherServlet
处理器映射器 HandleMapping
处理器适配器 HandleAdapter
Handle
视图解析器 ViewResovle

1.发送请求前端控制器 DispacherServlet
2. DispacherServlet调用处理器映射器HandleMapping,生成处理器对象和拦截器
3.DispatcherServlet 再调用处理器适配器HandleAdapter找到对应的handle
4.调用handle,返回模型视图,前端控制器再调用视图解析器解析视图
5.DispatcherServlet 对视图进行渲染,返回给用户。


11.说说spring mvc用了哪些技术怎么实现的?

答:拦截器 aop技术


12.Spring MVC常用的注解有哪些?

答:@RequestMapping url映射 、@RequestBody 将请求参数转为java对象、@ResponseBody将返回参数转为json格式。


13.springmvc是怎么向前台传递数据的?

答:通过modelMap对象把内容放到里面,前端就可以通过el表达式拿到。


14.springmvc拦截器是怎么写的?

答:实现HandlerInterceptor接口或者继承适配器类


15.WebApplicationContext是什么?

答:继承了ApplicationContext 并增加了一些WEB应用必备的特有功能.


16.springboot/spring常用的注解有哪些?

答:@import @Component @RequestMapping @Pathvariable @Bean @Scope @Configuration @Autowired @RequestBody @ResposeBody


17.怎么保证spring定时任务高可用?两个定时任务同时写表怎么处理的?

答:数据库方面:表主键约束避免重复插入,如果写的频率高,可以用悲观锁的方式,更新的时候加锁for update nowait,数额类更新:如果是累加的,可以写成update a =a+b 的方式,如果本次操作不可抛弃,可以增加重试功能。如果写的频率不高,可以用乐观锁,增加版本号字段来控制,写的时候带上版本号去更新。

18.说说springboot自动配置原理?

答:面试回答-->(springboot注解会引入后缀是xxImportSelector类,里面有selectImorts方法,它会寻找META-INF/spring.factories配置文件,找到里面的自动配置类,根据自动配置类进行装配。)

详细:

@SpringBootApplication里有@EnableAutoConfiguration ,@EnableAutoConfiguration里再@Import({EnableAutoConfigurationImportSelector.class})
他的父类AutoConfigurationImportSelector里面的selectImports方法会去寻找META-INF/spring.factories配置文件,配置文件里配置的EnableAutoConfiguration的自动配置类(比如springboot-autoconfigure META-INF/spring.factories 自动配置类)
根据自动配置类进行装配


19.Spring cloud知道多少?

答:五大组件eureka、zuul、Hystrix、ribbon、springcloud config,以及服务调用feign


20.@Autowired/@Resource的区别?

答:@Autowired是Spring的注解,Autowired默认先按byType,如果发现找到多个bean,则,又按照byName方式比对,如果还有多个,则报出异常。@Resource是jdk的注解,默认按名称装配,如果装配失败,按类型。

21.BeanFactory 和ApplicationContext的区别?

答:BeanFactory提供基本功能(实例化对象和获取对象),ApplicationContext提供更多的功能包括aop。装载bean方面,BeanFactory在拿bean的时候才实例化,ApplicationContext在启动的时候全部实例化。

22.Spring 定时任务执行原理是什么?

答:Spring 将会优先查找 TaskScheduler/ScheduledExecutorService的实例,若存在将会使用。如果不存在则使用的是 JDK 自带的 ScheduledExecutorService的默认配置。

23.spring执行多个定时任务怎么做?

答:配置一个TaskScheduler,设置好线程池大小,增加到spring容器中。如果不配置,则多个任务可能会互相影响(等待)。

24.spring是如何解决循环依赖的?

答:面试回答--》简单来说,主要是有三级缓存,在里面有发现循环依赖,就会临时放到二级缓存(表示有循环依赖的),最后都放到一级缓存里面去。

1.对象A一开始会放入三级缓存( singletonFactories),发现依赖B,也放入三级缓存;2.开始注入B中的依赖A时,把A从三级移到二级(删除三级中A);3.把B放进一级缓存,删除三级,完成B的注入;4.把A也放入一级缓存,删除二级缓存,完成A的注入。至此A,B注入完成。

详细: 

假设对象A中有属性是对象B,对象B中也有属性是对象A,即A和B循环依赖。

1.创建对象A,调用A的构造,并把A保存下来。
2.然后准备注入对象A中的依赖,发现对象A依赖对象B,那么开始创建对象B。
3.调用B的构造,并把B保存下来。
4.然后准备注入B的构造,发现B依赖对象A,对象A之前已经创建了,直接获取A并把A注入B(注意此时的对象A还没有完全注入成功,对象A中的对象B还没有注入),于是B创建成功。
5.把创建成功的B注入A,于是A也创建成功了。
于是循环依赖就被解决了。
  singletonObjects:单例对象的cache,一级缓存
  earlySingletonObjects :二级缓存,提前暴光的单例对象的Cache 。【用于检测循环引用,与singletonFactories互斥】
 singletonFactories : 单例对象工厂的cache ,三级缓存
 

步骤 操作 三层列表中的内容
1 开始初始化对象A

singletonFactories:

earlySingletonObjects:

singletonObjects:

2 调用A的构造,把A放入singletonFactories

singletonFactories:A

earlySingletonObjects:

singletonObjects:

3 开始注入A的依赖,发现A依赖对象B

singletonFactories:A

earlySingletonObjects:

singletonObjects:

4 开始初始化对象B

singletonFactories:A,B

earlySingletonObjects:

singletonObjects:

5 调用B的构造,把B放入singletonFactories

singletonFactories:A,B

earlySingletonObjects:

singletonObjects:

6 开始注入B的依赖,发现B依赖对象A

singletonFactories:A,B

earlySingletonObjects:

singletonObjects:

7

开始初始化对象A,发现A在singletonFactories里有,则直接获取A,

把A放入earlySingletonObjects,把A从singletonFactories删除

singletonFactories:B

earlySingletonObjects:A

singletonObjects:

8 对象B的依赖注入完成

singletonFactories:B

earlySingletonObjects:A

singletonObjects:

9

对象B创建完成,把B放入singletonObjects,

把B从earlySingletonObjects和singletonFactories中删除

singletonFactories:

earlySingletonObjects:A

singletonObjects:B

10 对象B注入给A,继续注入A的其他依赖,直到A注入完成

singletonFactories:

earlySingletonObjects:A

singletonObjects:B

11

对象A创建完成,把A放入singletonObjects,

把A从earlySingletonObjects和singletonFactories中删除

singletonFactories:

earlySingletonObjects: 

singletonObjects:A,B

12 循环依赖处理结束,A和B都初始化和注入完成

singletonFactories:

earlySingletonObjects:

singletonObjects:A,B


表格来自:https://blog.csdn.net/lkforce/article/details/97183065?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161417812716780262598115%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=161417812716780262598115&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-97183065.pc_search_result_cache&utm_term=spring+%E8%A7%A3%E5%86%B3%E5%BE%AA%E7%8E%AF%E4%BE%9D%E8%B5%96

其实最关键的是,为什么会出现循环依赖?

假如说只有一级缓存singletonObjects,A对象创建后放进来,再注入B,B对象创建后也放进singletonObjects。。。。B中也有依赖A,又会创建A对象。。。。所以问题的关键是:怎么取已经创建的对象,而三级缓存的作用就是为了:可以发现是否已经有对象的实例创建好了。

@Transitional失效的情况?

答:springmvc下controller上的@Transactional不生效;检查型异常不回滚,如FileNotFoundException;只作用在public修饰符上

Springmvc 中 DispatcherServlet 初始化过程    

答:入口是web.xml中配置的ds,ds继承了HttpServletBean,FrameworkServlet,通过其中的init方法进行初始化装载bean和实例,initServletBean是实际完成上下文工作和bean初始化的方法。 
 


JVM

1.JVM里,new出来的对象是在哪个区?

答:new出来的对象放在堆里,对象的引用放在栈里。

2.说说类加载有哪些步骤?

    答:类加载分三步:加载、连接(验证、准备和解析)和初始化。

加载:class文件加载到JVM内存(静态变量、常量放到方法区),产生Class对象。

  验证:验证class文件是否格式正确。

  准备:为静态变量分配内存并设置默认的初始值

  解析:将符号引用替换为直接引用  (栈帧里的动态链接也有一步符号引用转变为直接引用)

初始化:为类的静态变量赋予正确的初始值

3.说说JVM内存模型?

答:是一种规范,与线程共享有关,堆和方法区所有线程共享,需要对其制定规则规范。主内存:java所有变量都存储在主内存中。工作内存/线程本地内存:本线程用到的变量为主存中的副本拷贝。

4.说说JVM内存结构分别放什么?

    答:堆:对象和数组、字符串常量池。方法区:常量、静态变量,运行时常量池(字面量和符号引用)。虚拟机栈:局部变量、对象引用。程序计数器:记录线程执行位置,以便下一次继续执行。

本地方法栈:是一些native方法(c++实现)

5.说说常用的JVM参数?

答:-Xms128m  -Xmx128m   Xmn1g  -XX:SurvivorRatio=4  -XX:+UseG1GC

6.说说常用的JVM调优命令?

答:jps  jstack jinfo  jmap  jstat

7.你知道反汇编吗?

答:知道。会使用javap反汇编解读i++操作原理 ,反汇编后得到JVM指令,可以通过官方文档查看JVM指令集的解释。

  javap -c  xx.class

8.说说高cpu的排查过程?

答:top命令找到进程号,用ps命令找到线程号,然后转为16进制,最后使用jstack命令找到该线程号堆栈位置。

9.堆栈溢出如何跟踪?

答:事先启动增加堆溢出跟踪日志参数-XX:+HeapDumpOnOutOfMemoryError ,用mat工具查看。

10.说说一次GC流程是怎么样的?

答:普通对象进入年轻代eden区,大对象直接进入老年代。

年轻代回收机制:

1.对象进入伊甸区,填满后触发一次minor gc,还存活的对象会复制到其中一个存活区s0并清空伊甸区。

2.当伊甸区再一次填满后,再次触发minor gc,jvm会把伊甸区和s0还存活的对象复制到另一个存活区s1,同时清空伊甸区和s0区。

3.如果复制的过程发现空间不够,就会搬到老年代。

4.如果minorgc达到15次就会搬到老年代。

11.什么是stop the world(STW)?

答:GC前会执行STW操作。线程进入JVM设置的“安全点”,暂停所有运行中的线程,stop the world,然后开始GC。

什么情况下会发生栈内存溢出?

答:递归。 

什么情况下发生堆溢出?

答:对象一直增大,不释放。 比如循环里一直list.add

g1 和 cms 区别?    

答:Cms是以获取最短回收停顿时间为目标的收集器。基于标记-清除算法实现。比较占用cpu资源,切易造成碎片。 G1是面向服务端的垃圾收集器,是jdk9默认的收集器,基于标记-整理算法实现。可利用多核、多cpu,保留分代,实现可预测停顿,可控。 
 


SQL

1.什么是三范式和反三范式?(表设计)

答:1NF:每列属性唯一;2NF主键唯一;3NF属性不能与其他表属性产生冗余。反三范式:避免过多的关联查询,可以降低范式标准,适当冗余。

2.SQL优化常见的方式?

答:避免全表扫描、合理使用索引、避免返回大量数据给客户端、避免使用游标、避免频繁创建删除临时表。

3.oracle解析器解析顺序?

答:从右到左的顺序处理FROM子句中的表名,记录数少的表写在右边作为基础表。WHERE 解析自下而上,过滤大数据量的条件放后面。

4.ORACLE分页怎么做?

答:用rownum select xx from (select xx, rownum r from test1) tt where tt.r < 100;

5.行列转换怎么做?

答:1.decode函数或者case when;2.通过map_agg函数把两个列的多行的值,映射为map;3.通过UNION语句

6.oracle怎么查树?

答:用start with conect by  。   具体:start with pid=0  connect by (prior id)=pid

7.索引查询快的原因,索引使用什么排序?

答:索引就是以空间换时间,以特定的数据结构重新存储数据,减少查询次数。mysql就是用b+树


linux

1.说说你常用的命令?

答:ps 、grep、find 、more 、less、 top、du、df、touch、chmod

2.怎么查找文件中的字符串?

 答:如果只要找到字符串的那一行,用grep字符 文件名的方式,如果要找到字符串并且要能看到上下文,就用less,用斜杠加字符串查找,用n/N往上下查找。

less -mN a.txt    查看文件,/wzx  查找字符串,n继续往下找,N网上找。g跳到第一行,G跳到最后一行,q 退出
grep wzx a.txt    查找文件内容包含字符串

3.怎么查看java进程?

答:可以用jps,也可以用ps -ef|grep
ps -ef |grep xxx    查看进程

4.怎么查看cpu占用情况?

答:top    查看cpu占用情况

5.怎么查看磁盘占用情况?

答:df    查看磁盘占用情况
du * -sh    查看当前文件夹下空间占用(包含文件夹统计) ll -h 也可以查看文件占用

6.怎么更改环境变量?

vi /etc/profile    所有用户 。  立即生效:source /etc/profile
vi ~/.bash_profile    更改当前用户环境变量。立即生效: source ~/.bash_profile

7.你知道怎么自定义一个自己的命令吗?

答:写好命令脚本,然后再环境变量增加自定义命令文件扫描路径,并且立即生效。


多线程

1.说说常用的线程池有哪些?    

答:定长线程池(FixedThreadPool)、缓存线程池(CachedThreadPool)、单线程线程池(SingleThreadExecutor)、周期线程池

2.那你知道多线程JDK8有什么新特性?

答:增加异步编程CompletableFuture。可以对返回结果进行集中处理。

3.说说ThreadPoolExecutor有几个参数,分别是什么意思?

答:7个参数。核心线程大小、最大线程数、非核心线程超时时间、单位、阻塞队列、线程工厂、拒绝策略handle

4.线程有几种拒绝策略,分别是什么?实际应该怎么使用?


答:我知道有4种。单词记不住,面试回答--》一种是直接抛异常,一直是直接丢弃任务,还有一种是抛弃等待最久的任务,另外一种我忘了。

具体:

AbortPolicy    直接抛异常,程序中断。;CallerRunsPolicy  回退调用者
DiscardOldestPolicy  抛弃队列种等待最久的任务,尝试提交   DiscardPolicy   直接丢弃任务

使用:

具体使用要根据业务来,如果业务可以支持抛异常就用抛异常,如果任务可以丢弃就用丢弃策略,没有特定的方式。我看过一个框架重写的拒绝策略是什么都不处理,具体是哪个我忘了好像是apache。

5.说说线程池工作的过程?    

答:面试回答--》1.线程池添加任务,小于核心线程数,就创建执行;2.如果大于核心数,就进入阻塞队列;3.如果阻塞队列满了,就创建非核心线程执行新添加的任务;4.如果全满了,就根据拒绝策略处理。

详细:

1.线程池创建
2.执行execute()添加任务时:
执行execute()添加任务时:
当前线程数小于核心线程数,立即创建线程并运行。
否则,进入阻塞队列等待。
如果队列满了,就会创建非核心线程并立即执行。(注意,此时阻塞队列里的任务仍然在等待)。
如果还有任务进来,并且此时运行线程大于等于最大线程数,则启动饱和拒绝策略。

3.当线程中任务执行完成时,从队列取任务。
4.如果一个线程空闲,会根据空闲时间,判断是否大于核心线程数,如果大于就销毁线程,释放内存。

用过哪些原子类,他们的原理是什么?

    答:AtomicInteger; AtomicLong; AtomicReference; AtomicBoolean;基于CAS原语实现 ,比较并交换、加载链接/条件存储,最坏的情况下是旋转锁 

创建多少线程数合适?

    答:CPU 密集型(例如:1-1000 万累加计算)则是 CUP核心数+1,如果是IO 密集型(数据库访问,远程调用)则是:最佳线程数 = (1/CPU利用率) = 1 + (I/O耗时/CPU耗时)

Threadlocal原理和作用?  

 答:作用:每个线程提供变量副本,起到线程隔离的作用。原理:每个ThreadLocal类创建一个Map,然后用线程的ID作为Map的key,实例对象作为Map的value,这样就能达到各个线程的值隔离的效果。

countdowlatch 和 cyclicbarrier 的作用?  

 答:CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它运行一个或者多个线程一直处于等待状态。 CyclicBarrier要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。 

使用 synchronized 修饰静态方法和非静态方法有什么区别?

    答:对象锁和类锁

死锁产生的原因?  

 答:两个以上线程,争抢对方手中的资源,而自身又不释放。
 


Redis

这边看你写了解一点redis,能说说你是怎么用的吗?    

答:redis就是说,读的次数远大于写的次数,这个使用可以用redis作为缓存,提高读的效率。

缓存击穿、缓存穿透、缓存雪崩是什么?怎么解决?

答:缓存击穿:缓存没数据,数据库有数据,一般发生在过期的时候,给数据库压力。解决:热点数据永不过期,或者解锁,第一个进来锁上,第二个线程进来等待100ms再重新获取。

缓存穿透:缓存和数据库都找不到,用户一直去访问,造成数据库压力。解决:可以给KEY设置一个null值,然后设置一个很短的时间比如5分钟过期时间或者接口层增加id递减判断,如果小于0就拦截,或者用布隆过滤器。

缓存雪崩:就是同一时间大批量的KEY都过期了。可以分散它的过期时间来解决。

布隆过滤器的原理是什么?

答:就是把可能存在的哈希数据放到一个大的bitmap中,然后一个一定不存在的数据进来,就会被过滤掉。

友情链接:

程序员搞什么副业好?https://blog.csdn.net/x18094/article/details/113782544

猜你喜欢

转载自blog.csdn.net/x18094/article/details/113916157