java面试详细解答|2022年java开发面试题整理合集


文章目录

  • java基础知识面试题
        • 1. 面向对象的特征有哪些方面?
        • 2.什么是JDK,JDK 和 JRE 的区别是什么?
        • 3.== 和 equals()方法的区别?
        • 4.Java 有哪几种基本数据类型?
        • 5.访问修饰符 public,private,protected以及不写(defualt)时的区别?
        • 6.重载和重写的区别?
        • 7.this和super有什么区别?
        • 8.String和StringBuffer、StringBuilder的区别?
        • 9.接口和抽象类的区别是什么?
        • 10.final、finally、finalize有什么区别?
        • 11.什么是单例模式?有几种?
        • 12.List 和 Map、Set 的区别
        • 13.List、Map、Set三个接口存取元素时,各有什么特点?
        • 14.说说常见的集合有哪些?
        • 15.BIO、NIO、AIO 有什么区别?
        • 16.Hashmap和hashtable ConcurrentHashMap区别?
        • 17.什么是线程池?为什么要用线程池?
        • 18.Java中sleep()方法和wait()方法有什么区别?
        • 19.ArrayList 和 LinkedList 有何区别?
        • 20.Java常见异常有哪些?
        • 21.Java 中 IO 流分为几种?
        • 22.Java中创建多线程有几种方法?
        • 23. Runnable接口和Callable接口的区别?
        • 24.如何启动一个新线程、调用start和run方法的区别?
        • 25.线程有哪几种状态以及各种状态之间的转换?
        • 26。Java类加载器的流程
        • 27.讲一下你对ioc容器的理解(Inverse of Control 控制反转)
        • 28.Redis 的存储结构有哪些
        • 29.SpirngBoot的好处
        • 30.循环依赖碰到过吗?怎么解决

java基础知识面试题 1. 面向对象的特征有哪些方面? 面向对象的特征有抽象、继承、封装和多态性。
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
继承:继承是从现有类中得到继承信息来创建新类的过程,提供继承信息的类被称为父类,得到继承信息的类被称为子类。
封装:封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。
多态性:多态性允许不同子类型的对象对同一消息作出不同的响应,可分为编译时的多态性和运行时的多态性。
2.什么是JDK,JDK 和 JRE 的区别是什么? JDK 是 Java Development ToolKit 的简称,也就是 Java 开发工具包。
JRE是Java 运行时的环境和将要执行 Java 程序的虚拟机,同时包含了执行程序需要的浏览器插件。
JDK是完整的 Java 软件开发工具包,包含了 JRE,可以让开发者开发、编译、执行 Java 应用程序。
3.== 和 equals()方法的区别? ==的作用
基本类型:比较的就是值是否相同
引用类型:比较的就是地址值是否相同
equals的作用
引用类型:默认情况下,比较的是地址值。
特:String、Integer、Date这些类库中equals被重写,比较的是内容而不是地址!
==:比较的是两个字符串内存地址(堆内存)的数值是否相等,属于数值比较; equals():比较的是两个字符串的内容,属于内容比较。
4.Java 有哪几种基本数据类型?
整型有byte、short、int、long,浮点型有float、double,字符型有char、布尔型:boolean
5.访问修饰符 public,private,protected以及不写(defualt)时的区别? Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访问,支持 4 种不同的访问权限。
1.private : 在同一类内可见,使用对象:变量、方法,不能修饰外部类
2.default : 在同一包内可见,不使用任何修饰符,使用对象:类、接口、变量、方法。
3.protected : 对同一包内的类和所有子类可见,使用对象:变量、方法,不能修饰外部类。
4.public : 对所有类可见,使用对象:类、接口、变量、方法
6.重载和重写的区别? 重载: 发生在同一个类中,方法名必须相同,参数类型不同.个数不同.顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。
重写: 发生在父子类中,方法名.参数列表必须相同,返回值范围小于等于父类,抛出的异 常范围小于等于父类, 访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
7.this和super有什么区别?
this:代表当前对象本身,super:代表当前对象的父类。
8.String和StringBuffer、StringBuilder的区别? String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
String 中的String 类中使用 final 关键字修饰字符数组来保存字符串,private final char value[] ,String对象是不可变的,也就可以理解为常量,线程安全。
StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
9.接口和抽象类的区别是什么? 实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
构造函数:抽象类可以有构造函数;接口不能有。
main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符
10.final、finally、finalize有什么区别?
1.final可以修饰类、变量、方法,修饰类时表示该类不能被继承、修饰方法时表示该方法不能被重写、修饰变量时表示该变量是一个常量不能被重新赋值。
2.finally一般作用在try-catch代码块中,在处理异常的时候,通常将一定要执行的代码放在finally代码块中。表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
3.finalize是Object类的一个方法,它是用来实现垃圾回收的。在垃圾回收器执行时会调用被回收对象的finalize()方法,可以覆盖此方法来实现对其他资源的回收。
11.什么是单例模式?有几种? 单例模式:某个类的实例在 多线程环境下只会被创建一次出来。
单例模式有饿汉式单例模式、懒汉式单例模式和双检锁单例模式三种。
饿汉式:线程安全,一开始就初始化。
懒汉式:非线程安全,延迟初始化。
双检锁:线程安全,延迟初始化。
12.List 和 Map、Set 的区别 List和Set是存储单列数据的集合,Map是存储键值对这样的双列数据的集合。
List中存储的数据是有顺序的,并且值允许重复;
Map中存储的数据是无序的,它的键是不允许重复的,但是值是允许重复的;
Set中存储的数据是无顺序的,并且不允许重复,但元素在集合中的位置是由元素的hashcode决定,即位置是固定的(Set集合是根据hashcode来进行数据存储的,所以位置是固定的,但是这个位置不是用户可以控制的,所以对于用户来说set中的元素还是无序的)。
13.List、Map、Set三个接口存取元素时,各有什么特点? List存取元素时有放入顺序,元素可以重复
Map存取元素时按键值对存储,无放入顺序
Set存取元素时元素无放入顺序,元素不可以重复
14.说说常见的集合有哪些? 1.Collection接口的子接口包括:Set 接口和List 接口;
2.Map接口的实现类主要有:
HashSet
底层数据结构是哈希表。(无序,唯一)
如何来保证元素唯一性?
依赖两个方法:hashCode()和equals()
LinkedHashSet
底层数据结构是链表和哈希表。(FIFO插入有序,唯一)
1.由链表保证元素有序
2.由哈希表保证元素唯一
TreeSet
底层数据结构是红黑树。(唯一,有序)
1. 如何保证元素排序的呢?
自然排序
比较器排序
2.如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定
3.Set接口的实现类主要有:
HashSet
底层数据结构是哈希表。(无序,唯一)
如何来保证元素唯一性?
依赖两个方法:hashCode()和equals()
LinkedHashSet
底层数据结构是链表和哈希表。(FIFO插入有序,唯一)
1.由链表保证元素有序
2.由哈希表保证元素唯一
TreeSet
底层数据结构是红黑树。(唯一,有序)
1. 如何保证元素排序的呢?
自然排序
比较器排序
2.如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定
4.List接口的实现类主要有:
ArrayList
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程不安全,效率高
Vector
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程安全,效率低, 已给舍弃了
LinkedList
优点: 底层数据结构是链表,查询慢,增删快。
缺点: 线程不安全,效率高
15.BIO、NIO、AIO 有什么区别? BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
16.Hashmap和hashtable ConcurrentHashMap区别? 区别对比(HashMap 和 HashTable 区别):
1、HashMap 是非线程安全的,HashTable 是线程安全的。
2、HashMap 的键和值都允许有 null 值存在,而 HashTable 则不行。
3、因为线程安全的问题,HashMap 效率比 HashTable 的要高。
4、Hashtable 是同步的,而 HashMap 不是。因此,HashMap 更适合于单线
程环境,而 Hashtable 适合于多线程环境。一般现在不建议用 HashTable, ①
是 HashTable 是遗留类,内部实现很多没优化和冗余。②即使在多线程环境下,
现在也有同步的 ConcurrentHashMap 替代,没有必要因为是多线程而用
HashTable。
17.什么是线程池?为什么要用线程池? 线程池:就是事先创建多个可执行的线程放入一个容器中,需要的时候从容器中获取而不用自行创建。线程使用完毕时不需要销毁线程而是放回容器中,从而减少创建和销毁线程对象的开销。
使用线程池可以避免频繁地创建和销毁线程。
使用线程池可以根据项目灵活地控制并发的数目。
18.Java中sleep()方法和wait()方法有什么区别? sleep()方法和wait()方法都可以暂停线程的执行,区别在于:
1.类的不同:sleep() 方法是Thread线程类的静态方法,wait()方法是Object类的方法。
2.是否释放锁:sleep()方法不释放锁;wait()方法释放锁。
3.用途不同:wait()方法通常用于线程之间的通信,sleep()方法通常用于暂停执行。
4.用法不同:wait() 方法被调用后,超时之前线程不会自动苏醒,除非别的线程调用同一个对象上的 notify()方法或者notifyAll() 方法。sleep()方法执行完成后,线程会自动苏醒。
19.ArrayList 和 LinkedList 有何区别?
ArrayList支持随机访问而LinkedList不支持。
ArrayList是通过数组来实现,插入和删除会受到元素位置的影响而会产生移位。
LinkeList采用双向链表来存储数据,插入和删除不会受到元素位置的影响。
ArrayLIst会预留一定的空间,数组实际空间小于存储的空间。
linkedlist则不会预留空间,有元素添加才会去申请这个元素所对应的内存空间。
ArrayList执行频繁的查找效率比LinkedList高。
LinkedList执行频繁的插入和删除效率比Arraylist高
20.Java常见异常有哪些?
java.lang.IllegalAccessError:违法访问错误。当一个应用试图访问、修改某个类的域(Field)或者调用其方法,但是又违反域或方法的可见性声明,则抛出该异常。
java.lang.InstantiationError:实例化错误。当一个应用试图通过Java的new操作符构造一个抽象类或者接口时抛出该异常.
java.lang.OutOfMemoryError:内存不足错误。当可用内存不足以让Java虚拟机分配给一个对象时抛出该错误。
java.lang.StackOverflowError:堆栈溢出错误。当一个应用递归调用的层次太深而导致堆栈溢出或者陷入死循环时抛出该错误。
java.lang.ClassCastException:类造型异常。假设有类A和B(A不是B的父类或子类),O是A的实例,那么当强制将O构造为类B的实例时抛出该异常。该异常经常被称为强制类型转换异常。
java.lang.ClassNotFoundException:找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
java.lang.ArithmeticException:算术条件异常。譬如:整数除零等。
【java面试详细解答|2022年java开发面试题整理合集】java.lang.ArrayIndexOutOfBoundsException:数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
java.lang.IndexOutOfBoundsException:索引越界异常。当访问某个序列的索引值小于0或大于等于序列大小时,抛出该异常。
java.lang.InstantiationException:实例化异常。当试图通过newInstance()方法创建某个类的实例,而该类是一个抽象类或接口时,抛出该异常。
java.lang.NoSuchFieldException:属性不存在异常。当访问某个类的不存在的属性时抛出该异常。
java.lang.NoSuchMethodException:方法不存在异常。当访问某个类的不存在的方法时抛出该异常。
ava.lang.NullPointerException:空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等。
ava.lang.NumberFormatException:数字格式异常。当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常。
java.lang.StringIndexOutOfBoundsException:字符串索引越界异常。当使用索引值访问某个字符串中的字符,而该索引值小于0或大于等于序列大小时,抛出该异常。
21.Java 中 IO 流分为几种?
  • 按照IO流的流向分,可以分为输入流和输出流
  • 按照IO流的操作单元划分,可以分为字节流和字符流
  • 按照IO流的实现功能划分,可以分为节点流和处理流
22.Java中创建多线程有几种方法?
  • 继承Thread类并重写 run 方法创建线程,实现简单但不可以继承其他类
  • 实现Runnable接口并重写 run 方法。避免了单继承局限性,编程更加灵活,实现解耦。
  • 实现 Callable接口并重写 call 方法,创建线程。可以获取线程执行结果的返回值,并且可以抛出异
    常。
  • 使用线程池创建(使用java.util.concurrent.Executor接口)
23. Runnable接口和Callable接口的区别?
Runnable接口的run()方法无返回值,只能抛出运行时异常,且无法捕获处理。
Callable接口的call()方法有返回值,允许抛出异常,可以获取异常信息。
24.如何启动一个新线程、调用start和run方法的区别? 线程对象调用run方法不开启线程。仅是对象调用方法。
线程对象调用start开启线程,并让jvm调用run方法在开启的线程中执行
调用start方法可以启动线程,并且使得线程进入就绪状态,而run方法只是thread的一个普通方法,还是在主线程中执行。
25.线程有哪几种状态以及各种状态之间的转换?
  1. 第一是new->新建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
  2. 第二是Runnable->就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。
  3. 第三是Running->运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
  4. 第四是阻塞状态。阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
    (1)等待 – 通过调用线程的wait() 方法,让线程等待某工作的完成。
    (2)超时等待 – 通过调用线程的sleep() 或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
    (3)同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
  5. 第五是dead->死亡状态: 线程执行完了或者因异常退出了run()方法,该线程结束生命周期
    java面试详细解答|2022年java开发面试题整理合集
    文章图片
26。Java类加载器的流程 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中验证、准备、解析3个部分统称为连接(Linking)。
7个阶段发生顺序如下图所示:
java面试详细解答|2022年java开发面试题整理合集
文章图片

27.讲一下你对ioc容器的理解(Inverse of Control 控制反转) Spring提供了两种容器类型
  • BeanFactory
  • ApplicationContext
BeanFactory
基础类型IoC容器,提供完整的IoC服务支持,如果没有特殊指定,默认采用延迟初始化策略。只有当客户端对象需要访问容器中的某个受管对象的时候,才对该受管对象进行初始化以及依赖注入。所以相对来说,容器启动初期速度较快(因为延迟初始化了),所需要的资源有限。对于资源有限,并且功能要求不是很严格的场景,BeanFactory是比较适合的。但话说回来,Bean工厂对大多数应用来说往往太低级了,所以一般不使用
ApplicationContext
ApplicationContext是在BeanFactory的基础上构建的,是相对比较高级的容器实现,除了用于Bean工厂的所有支持,ApplicationContext还提供了其他高级用法,比如事件发布等
ApplicationContext间接继承自BeanFactory
28.Redis 的存储结构有哪些
String,字符串,是 redis 的最基本的类型,一个 key 对应一个 value。是二进制安全的,最大能存储 512MB。
Hash,散列,是一个键值(key=>value)对集合。string 类型的 field 和value 的映射表,特别适合用于存储对象。每个 hash 可以存储 232 -1 键值对(40 多亿)
List,列表,是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列边或者尾部(右边)。最多可存储 232 - 1 元素(4294967295, 每个列表可存储 40 亿)
Set,集合, 是 string 类型的无序集合,最大的成员数为 232 -1(4294967295, 每个集合可存储 40 多亿个成员)。
Sorted set,有序集合,和 set 一样也是 string 类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。zset 的成员是唯一的,但分数(score)却可以重复。
29.SpirngBoot的好处
(1)简化配置,不需要编写太多的xml配置文件
(2)基于Spring构建,使开发者快速入门,门槛很低
(3)SpringBoot可以创建独立运行的应用而不需要依赖于容器
(4)内置tomcat服务器,不需要打包成war包,可以直接放到tomcat中运行
(5)提供maven极简配置,以及可视化的相关监控功能,比如性能监控,应用的健康程度等
(6)为微服务SpringCloud奠定了基础,使得微服务的构建变得简单
(7)Spring可以整合很多各式各样的框架,并能很好的集成
(8)活跃的社区与论坛,以及丰富的开发文档
30.循环依赖碰到过吗?怎么解决 什么是循环依赖
当一个ClassA依赖于ClassB,然后ClassB又反过来依赖ClassA,这就形成了一个循环依赖:
ClassA -> ClassB -> ClassA
①构造器的循环依赖:这种依赖spring是处理不了的,直 接抛出BeanCurrentlylnCreationException异常。
②单例模式下的setter循环依赖:通过“三级缓存”处理循环依赖。
③非单例循环依赖:无法处理。

    推荐阅读