面试题大全<持续更新>

这篇博客汇总了Java面试中的重要知识点,包括重载与重写、String与StringBuilder的区别、==与equals的对比、synchronized关键字的使用、抽象类与接口的区别、集合框架的特性、线程相关概念与实现、并发编程、Spring框架和SpringBoot的运用,以及SpringCloud的核心组件。此外,还详细阐述了HashMap和HashSet的实现原理,线程池的工作模式,以及Redis的多种使用场景和数据类型。这些内容全面覆盖了Java开发者的面试必备知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.重载和重写的区别?

       1.重载发生在一个类中,同名的方法如果有不同的参数列表(类型不同、个数不同、顺序不同)则视为重载.

        2.重写发生在子类与父类之间,重写要求子类重写之后的方法和父类被重写的方法有相同的返回类型,比父类更好访问,不能比父类被重写的方法声明更多的异常。

2.string和stringBuffer和StringBuilder的区别是什么?

        1.可变性:

             String类中使用final关键字来修饰字符数组来保存字符串,所以String对象是不可以改变的。而StringBuider和StringBuffer都继承自AbstractStringBuider类,AbstractStringBuider中也是使用字符数组来保存字符串的,但是没用final关键字来修饰,所以这两个对象是可以改变的。

        2.线程安全性

                由于String对象是不可以改变的,可以理解为常量,线程安全。

StringBuffier对方法加了同步锁或者对调用的方法加了同步锁,所以线程是安全的。

StringBuider并没有对方法加同步锁,所以是非线程安全的。

        3.性能

                每次对String类型进行改变的时候,都会生成一个新的string对象.然后将指针指向新的String对象,而StringButter每次都会对本身进行操作,而不是生成新的对象并引用,相同情况下StringBulider相比使用StringBuffer仅能获得10~15%的性能提升,但却要冒多线程不安全的风险。

 3.==与equals的区别

        1.对于基本类型和引用类型==作用效果是不同的,

        基本类型:比较的是值是否相同。

        引用类型:比较的是引用是否相同。

equals本质上就是==,只不过String和Integer等重写了equals方法,把它当作值比较.

  4.说说自己是怎么使用synchronized 关键字的,在项目中用到了吗?

        1.修饰实例的方法:作用于当前对象实例枷锁,进入同步代码前要获得当前对象实例的锁。

        2.修饰静态方法: 作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁。

        3.修饰代码块,指定枷锁对象,在进入同步代码块前要获得给定对象的锁。

        4.双重校验实现对象单例(线程安全)

   5.抽象类和接口的区别是什么?

        1.实现:抽象类的子类使用extends来继承:接口必须使用implements来实现接口。

        2.构造函数:抽象类可以有多个构造函数,接口不能有。

        3.实现数量:类可以实现很多的接口:但只能继承一个抽象类【java只支持单继承】

        4.访问修饰符:接口中的方法默认使用,public修饰:抽象类中的抽象方法可以使用public和protected修饰,如果抽象方法修饰符为private,则报错

        5.设计层面:抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范.

6.Collection和Collections有什么区别?

1.Collection是一个集合接口,他提供了对集合对象进行基本操作的通用接口的方法,所有集合都是他的子类,比如List.Set等。Collections是一个包装类,包含了很多静态的方法,不能被实例化,就像是一个工具类,比如提供的排序方法:Collections.sort(list)

7.List、Set、Map之间有什么区别?

List、Set、Map的区别主要体现在两个方面:元素是否有序、是否元素重复。

三者之间的区别如下表:

8.HashMap和Hashtable有什么区别?

1.存储:HashMap运行key和value为null,而Hashtable不允许。

2.线程安全:Hashtable是线程安全的,而HashMap则是非线程安全的。

3.推荐使用:在Hashtable的类注释上可以看到,Hashtable是一个保留类不建议使用,推荐在单线程的环境下使用HashMap代替,如果需要多线程则用ConcurrentHashMap代替。

9.说一下HashMap的实现原理?

        HashMap基于Hash算法实现的,我们通过put(key,value)存储,get(key)来获取。当传入key时,HashMap会根据key.hashCode()计算出hash值,根据hash值将value保存在bucket里,当计算出的hash值相同时,我们称之为hash冲突,HashMap的做法是用链表和红黑树来存储相同的hash值的value。当hash冲突个数比较少时,使用链表否则使用红黑树。

10.说一下HashSet的实现原理?

        HashSet基于HashMap实现的,HashSet底层使用HashMap来保存所有的元素,因此HashSet的实现比较简单,相关于HashSet的操作,基本上都是直接调用底层的HashMap的相关方法来完成的,HashSet不允许重复的值。

11.ArrayList和LinkedList的区别?

        ArryList:基于动态数组,连续内存存储,适合下标访问,扩容机制:因为数组长度固定,超出的长度存数据时需要新建数组,然后将老数组的数据拷贝到新的数组中,如果不是尾部插入数据则还会涉及到元素的移动,使用尾插法并指定初始容器可以极大提高性能,甚至超过LinkedList。

        LinkedList:基于链表,可以存储在分散的内存中,适合做数据的删除和插入操作,不适合查询:需要逐一遍历,遍历LinkedList必须使用Iterator,不能使用for循环,因为每次for循环体内通过get某个元素时都需要对list重新进行遍历,性能消耗极大。

12.ConcurrentHashMap原理,jdk7和jdk8版本的区别

jdk7:

         数据结构:ReentrantLock+Segement+HashEntry,一个Segement中包含一个HashEntry数组,每个HashEntry又是一个链表结构。

        元素查询:二次Hash,第一次Hash定位到Segment,第二次Hash定位到元素所在的链表头部。

        锁:Segment分段锁,Segment继承了ReentrantLock,锁定操作的Segment,其他Segment不受影响,并发度为Segment的个数,可以通过构造函数来指定,数组扩容不影响其他Segment get的方法无须加锁,Volatile保证。

jdk8:

        数据结构:synchronized+CAS+Node+红黑树,Node的val和next都用Volatile来修饰,保证可见性。

        查找,替换,赋值操作都使用CAS。

        锁:所链表的head节点,不影响其他元素的读写,锁粒度更细,效率更高,扩容时,阻塞所有读写操作,并发扩容。

读操作无锁:Node的val和next使用Volatile修饰,读写线程对该变量互相可见。

数组使用Volatile来修饰,保证扩容时被读线程感知。

13.哪些集合类是线程安全的?

        Vector、Hashtable、Stack都是线程安全的,而像HashMap则是非线程安全的,不过在jdk1.5之后随着java.util.concurrent并发包的出现,他们也有了自己对应的线程安全类,比如HashMap对应的线程安全类就是ConcurrentHashMap。

14.创建线程有哪几种方式?

创建线程有三种方式:

 1.继承Thread重写run方法;

  2.实现Runnable接口;

  3.实现Callable接口;

15.说一下runnable和callable有什么区别?

runnble没有返回值,callable可以拿到返回值,callable可以看作是runable的补充。

16.线程有哪些状态?

        当线程对象创建后,进入新建状态;当调用对象的start()方法,线程即进入就绪(Runnable);CPU获取时间片,进入运行状态(Running);当线程调用wait()或者sleep()时,进入阻塞状态(Blocked),当休眠时间结束后,或者调用notify或者notifyAll时会重新进入就绪状态(Runble),在重新获取时间片,进入运行状态,线程执行完了或者因异常退出run()方法,该线程结束生命周期,进入终结状态(Dead)。

17.sleep()和wait()有什么区别?

类的不同:sleep来自Thread,wait()来自Object。

释放锁:sleep()不释放锁;wait()释放锁。

用法不同:sleep()时间到会自动恢复;wait()可以使用notify()或者notifyAll()直接唤醒。

18.notify和notifyAll()有什么区别?

        notifyAll()会唤醒所有的线程,notify()唤醒一个线程,notifyAll()调用后,会将全部线程由等待池转移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争,而notify()只会唤醒一个线程,具体唤醒哪一个,线程由虚拟机控制。

19.线程的run()和start()有什么区别?

        start()方法用于启动线程,run()方法用于执行线程运行时的代码,run()方法可以重复调用,start()只能被调用一次。 

20.说一说集中常见的线程池及适用场景?

1.FixedThreadPool:可重用于固定线程数的线程池。(适用于负载比较重的服务器)

2.SingleTheradExecutor:只会创建一个线程执行任务。(适用于需要保证顺序执行各个任务;并且任意时间点,没有多线程活动的场景)

3.CachedThreadPool:是一个会根据需要调整线程数量的线程池。(大小无界,适用于很多的短期的异步任务小程序,或负载比较轻的服务器)

4.ScheduledThreadPool:继承自ThreadPoolExecutor。它主要用来给定延迟之后的运行任务,或者定期执行任务。使用DelayQueue作为任务队列。

21.线程池种submint()和execute()方法有什么区别?

execute():只能执行Runable类型的任务。

submint():可以执行Runable和Callable类型的任务。

Callable类型的任务可以获取执行的返回值,而Runable执行无返回值。

22.在java程序中怎么保证多线程的运行安全?

方法一:使用安全类,比如java.util.concurrent下的类。

方法二:使用自动锁synchronized。

方法三:使用手动锁 Lock。

23.什么是死锁?

        当线程A持有独占锁a,并尝试去获取独占锁b的同时,线程B持有独占锁b,并尝试去获取独占锁a的情况下,就会发生AB两个线程由于互相持有对方所需要的锁,就会发生阻塞的现象,我们称为是死锁。

24.怎么防止死锁?

1.尽量使用tryLock(long timeout,TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。

2.尽量使用Java.util.concurrent并发类代替自己手写锁。

3.尽量降低锁的使用粒度,尽量不要几个功能同用一把锁。

4.尽量减少同步代码块

25.ThreadLocal是什么?有哪些使用场景?

1.ThreadLocal为每个使用变量的线程提供独立的变量副本,所以每一个线程都可以独立改变自己的副本,而不会影响其他线程对应的副本。

2.ThreadLocal的经典使用场景是数据库的连接和session管理等。

26.synchronized和Lock有什么区别?

1.synchronized可以给类、方法、代码块加锁:而lock只能给代码块加锁。

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

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

27.什么是Java序列化?什么情况下需要序列化?

        Java序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态在读取出来。

以下情况下需要Java序列化:

        1.想把内存中的对象状态保存到一个文件中或者数据库中的时候。

        2.想把套接字在网络上传送对象的时候。

        3.想通过RMI(远程方法调用)传输对象的时候。

28.动态代理是什么?有哪些应用?

动态代理就是运行时动态生成的代理类。

应用:

        动态代理的应用有:spring aop、rpc、java注解对象获取等。

29.怎么实现动态代理?

        JDK动态代理和cglib动态代理。JDK原生动态代理是基于接口实现的,而cglib是基于继承当前类的子类实现额。

30.为什么要克隆?

        克隆的对象可能包含一些已经修改过的属性,而new出来的对象属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的"状态"就靠克隆的方法了。

31.session和cookie有什么区别?

1.存储的位置不同:session存储在服务器端。cookie存储在浏览器端。

2.安全性不同:cookie安全性一般,在浏览器存储,可以被伪造和修改。

3.容量和个数的限制:cookie有容量的限制,每个站点下的cookie也有个数的限制。

4.存储的多样性:session可以存储在Redis中、数据库中、应用程序中。而cookie只能存储在浏览器中。

32.如何避免SQL的注入?

1.使用预处理PreparendStatement。

2.使用正则表达式过滤掉字符中的特殊字符。

33.throw和throws的区别?

1.throw:是真实抛出的一个异常。

2.throws:声明可能会抛出的一个异常。

34.final、finally、finalize有什么区别?

1.final:是修饰符,如果修饰类,此类不能被继承。如果修饰方法和变量,则表示此方法和此变量不能在被改变,只能使用。

2.fanally:是try{}chtch{}finally{}最后一部分,表示不论发生任何的情况,都会执行,fanally部分可以省略,但如果finally部分存在,则一定会执行finally里面的代码。

3.finalize:是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。

35.常见的异常类有哪些?

1.空指针异常(NullPointerException)

2.指定类不存在(ClassNotFoudException)

3.字符串转换为数字异常(NumberFormatException)

4.数组下标越界异常(IndexOutfBoudsException)

5.数据类型转换异常(ClassCastException)

6.文件未找到异常(FileNotFoudException)

7.方法不存在异常(NoSuchMethodException)

8.Io异常(NoSuchMethodException)

9.Socket异常(SocketException)

36.说一下啊你熟悉的设计模式?

1.单例模式:保证被创建一次,节省系统开销。

2.工厂模式:解耦代码。

3.观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,他的所有的依赖着都会收到通知并自动更新。

4.外观模式:提供一个统一的接口,用来访问子系统的一群接口,外观定义了一个高层的接口,让子系统更容易使用。

5.模板方法模式:定义了一个算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。

6.代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。

37.spring框架使用了哪些设计模式?

1.spring的bean的创建默认使用的是单列模式。

2.spring中获取bean对象通过的是工厂模式。

3.spring中的aop采用的是动态代理模式。

4.在各种工厂以及配置文件实现中也都用到模板模式。

38.为什么要使用spring?

1.spring提供了ioc技术,容器会帮你管理依赖的对象,从而不需要自己创建和管理依赖的对象了,更轻松的实现了程序的解耦。

2.spring提供了事务的支持,使得事务操作变得更加得方便。

3.spring提供了面向切片编程,这样可以更方便得处理某一类的问题。

4.更方便的框架的集成,spring可以很方便的集成其他的框架,比如Mybatis等。

39.spring常用的注入方法有哪些?

1.setter属性的注入

2.构造方法的注入

3.注解方式的注入

40.spring事务实现方式有哪些?

声明式事务:声明式事务也有两种实现方式,基于xml配置文件的方式和注解方式(在类上添加@Transaction注解)。

编码方式:提供编码的形式管理和维护事务。

41.并发事务会带来哪些问题?

        1.脏读(Dirty read):当一个事务正在访问数据并对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,并使用了该数据,因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据就是"脏数据"依据"脏数据"所作的操作可能是不正确的。

        2.丢失修改:当一个事务读取一个数据时,另外一个事务也访问了这个数据,那么在第一个事务中修改了这个数据,另外一个事务也修改了该数据,那么第一个事务的修改结果就被丢失,因此称为丢失修改。

        3.不可重复读:指在一个事务多次读同一数据。在这个事务还没有结束时,另一个事务也访问了这个数据,那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样,这就发生了在一个事务中两次读到的数据是不一样的情况,因此称之为不可重复读。

        4.幻读:幻读和不可重复读类似,他发生在一个事务多次读取几行数据,接着另一个事务插入了一些数据时。在随后的查询中,第一个事务就会发现多了一些原本不存在的记录,就好像是发生了幻觉一样,所以被称为幻读。

42.事务的隔离级别有哪些?

        1.读取未提交:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读和不可重复读。

        2.读取已提交:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读和不可重复读仍有可能发生。

        3.可重复读:对同一字段多次读取的结果是一致的,除非数据是被本身的事务自己所修改,可以组织脏读和不可重复读,但幻读仍有可能发生。

        4.可串行化:最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

43.说一下springMVC运行流程?

1.springMVC先将请求发送给DispatcherServlet。

2.DispatcherServlet再把请求提交到对应的Controller。

3.Controller进行业务逻辑处理后,会返回一个ModelAndview。

4.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象。

5.视图对象负责渲染返回给客户端。

44.springMVC有哪些组件?

1.前置控制器

2.映射控制器

3.处理器

4.模型和视图

5.视图解析器

45.springMVC常见的注解

1.@controller 作用在类上表示该类为控制层类

2.@RequestMapping用来处理请求地址映射的注解

3@Pathvariable用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。

4.@requestParm主要用于在SpringMVC后台控制层获取参数值。

5.@ResponseBody:该注解用于将Controller的方法返回的对象转换为json对象格式。

6.@RequestBody用于接收前端传过来的json实体,接收参数也是对应的实体。

46.Redis是什么?都有哪些使用场景?

1.Redis是一个使用C语言开发的高速缓存数据库。

2.Redis使用场景:

        ■记录帖子点赞数、点击数、评论数。

        ■缓存近期热点数据

        ■记录用户会话信息

47.Redis有哪些功能?

■数据库缓存功能

■分布式锁的功能

■支持数据持久化

■解决分布式会话

48.什么是缓存穿透?怎么解决?

        1.缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库中去查询,造成缓存穿透。

        解决:

■最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

■另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空,我们仍然把这个空结果进行缓存,但他的过期时间会很短,最长不超过五分钟。

49.什么是缓存击穿?如何解决?

        1.缓存击穿是指缓存中没有但是数据库中有的数据,(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大的压力。

缓存击穿的解决方案:

        ■设置永远不过期。

        ■使用互斥锁(mutex key)业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候,不是立即取loaddb,而是先使用缓存工具的某些带成功操作的返回值的操作,去set一个mutex key,当操作成功时,在进行load db的操作并回设缓存:否则,就重试整个get缓存的方法。

50.什么是缓存雪崩?如何解决?

        1.缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机,和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩式不同数据都过期了,很多数据都查不到从而查询数据库。

解决方案:

        ■缓存数据的过期时间设置随机,防止同一时间大量数据过期发生。

        ■如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。

        ■设置热点数据永远不过期。

51.Redis支持的数据类型有哪些?

        Redis支持的数据类型:String(字符串)、list(列表)、hash(字典)、set(集合)、set(集合)。

52.怎么保证缓存和数据库数据一致性?

1.合理设置缓存的过期时间。

2.新增、更改、删除数据库操作时同步更新Redis,可以使用事务机制来保证数据的一致性。

53.Redis持久化有几种方式?

Redis的持久化有两种方式,或者说是两种策略:

        ■DB:指定的时间间隔能对你的数据进行快照存储。

        ■AOF:每一个收到的写命令都通过write函数追加到文件中。

54.Redis怎么实现分布式锁?

        1.Redis分布式锁其实就是在系统里面占一个“坑”,其他的程序也要占“坑”的时候,占用成功了就可以继续执行,失败了就只能放弃或者稍后重试。

        2.占坑一般使用setnx指令,只允许一个被程序占有,使用完调用del释放锁。

55.Redis淘汰策略有哪些?

1.volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。

2.volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。

3.volatile-random:从已设置过期时间的数据集中任意选中数据淘汰。

4.allkeys-lru:从数据集中挑选最近最少使用的数据淘汰。

5.no-enviction(驱逐):禁止驱逐数据。

56.MyBatis中#{}和${}的区别时什么?

        #{}是预编译处理,${}是字符替换。在使用#{}时,MyBatis会将SQL中的#{}替换成?,配合preparedStatement的set方法赋值,这样可以有效的防止SQL的注入,保证程序的运行安全。

57.什么地方使用${}

$的作用是字符拼接,不能防止sql的注入,当使用${}参数作为字段名或表名时使用。

58.当实体类的属性名和表中的字段名不一致如何处理?

1.通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。

2.通过<resultMap>类映射字段名和实体类属性名的一一对应的关系。

59.MyBatis如何实现一对多?

再resultMap中使用collection标签。

60.ResultType和ResultMap的区别?

        1.resultMap:reusulmap如果查询出来的列名和pojo的属性名不一致,通过定义一个resulmap对列名和pojo之间做一个映射关系。
        2.resulttype:resultType使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。

61.什么是springboot以及作用?

springboot是为了spring服务的,是用来简化新的spring应用的初始搭建以及开发过程的。

作用:

         ■配置简单

         ■独立运行

         ■自动装配

         ■代码生成和xml配置

         ■提供应用监控

         ■易上手

         ■提升开发效率

62.springboot核心配置文件是什么?

springboot核心的两个配置文件:

        ■bootstrap:bootstrap由父ApplicationContext加载的,比applicaton优先加载,而且bootstrap里面的属性不能被覆盖。

         ■application:用于springboot项目的自动化配置。

63.springboot自动装配原理

1.里面有一个main方法运行了一个run()方法, 再run方法必须要传入一个被@SpringBootApplication注解的类。

2.@SpringBootApplication包含@EnableAutoConfiguration该注解,@EnableAutoConfiguration开启自动装配功能,在@EnableAutoConfiguration中包含@Import注解({AutoConfigurationImportSelector.class})注解,该注解需要导入AutoConfigurationImportSelector自动配置类会完成响应的自动装配。

64.什么是springcloud?

1.spring cloud 是一系列的有序集合,他利用springboot的开发便利性巧妙的简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用springboot的开发风格做到一键启动和 部署。

65.springcloud的核心组件有哪些?

■nacos:服务注册于发现。

■Feign:基于动态代理机制,根据注解和选择的机器,拼接请求url地址,发起请求。

■Ribbon:实现负载均衡,从一个服务的多台机器中选择一台。

■Semtinel:提供了流量的控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。

■Gateway:网关管理,有gateway网关转发请求给对应的服务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值