2023年Java最新面试题,附详解答案

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 2023年Java最新面试题,附详解答案

写在前面:本篇面试题整理是我在广州地区进行面试整理得出,常见的基本都在下面了。基本都是可以直接在面试时用白话回答的答案总结,面试时照此回答即可,有其他常见面试问题也欢迎在评论区补充。


首次发布:202 3年 1月

更新日期:2023年 5月


2023年1月更新修改了一些可能造成误解的回答,并使用粗体将回答的关键部分标出,你可以使用便于自己记忆的方法组织语言来回答,只需要回答中包含这些答案关键字即可。


20210405194351216.jpg


2023年最新常见Java开发面试题、面试常问Java面试题整理(附白话答案)


一、Java基础部分面试题


1. Java面向对象的三个特征


封装 :对象只需要 选择性的对外公开一些属性和行为 。

继承 :子对象可以 继承父对象的属性和行为 ,并且可以在其之上进行修改以适合更特殊的场景需求。

多态 : 允许不同类的对象对同一消息做出响应 。


2. Java中基本的数据类型有哪些 以及他们的占用字节


image.png


3. int和Integer的区别


int是Java中的 原始类型 ,Integer是Java为int提供的 封装类 ,他们有不同的特征和用法,包括 大小、速度、默认值


4. String、StringBuilder、StringBuffer的区别及使用场景


String一旦定义就 不可改变 ,可空赋值。操作少量数据时使用。

StringBuilder 可改变,线程不安全 。操作单线程大量数据时使用。

StringBuffer 可改变,线程安全 。操作多线程大量数据时使用。


5. ArrayList、Vector和LinkedList的区别及使用场景


ArrayList和Vector都是 使用数组方式存储数据 ,允许 按序号索引元素 ,但是插入数据会涉及到元素移动等内存操作,所以

索引快插入慢 。


ArrayList懒加载 默认大小10 每次扩容1.5倍 线程不安全 性能较高

Vector 实例化时初始化 默认大小10 每次扩容2倍 线程安全 性能较低 已弃用


额外回答加分项:

多读少写建议使用CopyOnWriteArrayList

CopyOnWriteArrayList原理是发生修改的时候复制一份

多写少读或读写比较均匀建议使用Connections.synchronizedList


LinkedList 使用 双向链表 方式存储数据,插入只需要记录本项的前后项,索引需要向前或向后进行遍历,所以 插入速度较快,线程不安全

,频繁在任意位置插入和删除的情况可以使用,如果需要多线程访问,可以使用Connections.synchronizedList()或ConcurrentLinkedQueue


6. Collection和Collections的区别


Collection是 集合类上级接口 ,继承他的主要有List和Set

Collections是 集合类的帮助类 ,提供了对集合的搜索、排序、线程安全化等操作。


7. List和Map的区别


List是 存储单列数据的集合 ,Map是 存储键值对双列数据的集合 。

List存储的数据是 有顺序且可重复 的,Map存储的数据是 无顺序,键不可重复,值可重复的 。


8. HashMap和HashTable的区别


HashMap是Map接口的实现, 非线程安全,允许空键值 。

HashTable是Dictionary的子类, 线程安全,不允许空键值 。几乎被淘汰,建议使用ConcurrentHashMap来替代它。

HashMap使用的是快速失败迭代器,在迭代器创建后,除非通过迭代器自身的remove或者add方法,其他任何方式的修改都会抛出异常。


9. HashMap底层实现原理和扩容机制


JDK1.8以前: 数组+单链表 的组合,以键值对的方式存储元素。

JDK1.8及以后:引入 红黑树 结构,添加元素时,若 链表个数大于8,链表会转换为红黑树 ,反之 小于6时会修剪或还原成链表结构

选择6和8可以有效防止频繁的链表和红黑树转换。

扩容条件:


  1. 存放新值的时候当前已有元素个数大于阈值。
  2. 存放新值的时候当前存放数据发生hash碰撞(当前key计算的hash值换算出来的数组下标位置已经存在值)

默认容量是16,负载因子0.75,所以扩容阈值是12。

每次扩容的容量是原有的2倍。


10. HashMap什么样的类适合作为键


String最为常见,因为String对象不可变,且 重写了equals和hashcode方法 。

不可变性是必要的 ,如果key的hashcode存入和获取是不一致,就无法找到。

获取对象时需要用到equals和hashCode方法,正确的重写这两个方法是非常重要的,因为两个不相等的对象返回不同的hashCode的话,碰撞的几率就会小些,就可以提高HashMap的性能。


11. final、finally、finalize的区别


final 用于修饰属性、方法和类,分别表示 属性不可变,方法不可覆盖,类不可继承 。

finally 是 异常处理语句结构 的一部分,表示总是执行。

finalize 是Object类的一个方法,在 GC执行时会调用被回收对象的此方法 。


12. sleep()和wait()的区别


sleep()是 Thread类 的,wait()是 Object类 的方法

sleep不会释放锁,wait会释放锁。

sleep可在任意地方使用,wait notify notifyAll只能在synchronized块\方法中使用。

sleep必须捕获异常,而wait不需要。


13. 抽象类和接口的区别、以及使用场景


抽象类中可以有构造方法、静态方法、普通方法、普通成员变量。接口中不能有。

抽象类中的抽象方法访问类型可以是public、protected和默认类型,接口中只能是public。

抽象类中的静态成员变量访问类型可以任意,接口中只能是public的。

一个类只能继承一个类,但是可以实现多个接口。

抽象类和子类为“是不是”的关系。主要用于为一些类提供公共实现代码。

接口和实现为“有没有”的关系。主要用于代码的扩展性和可维护性。


14. Overload(重载)和Override(重写)的区别


重载 是一个类中多态性的一种表现, 在一个类中定义了多个同名的方法,他们有不同的参数列表 。

重写 是父类与子类之间多态的一种表现, 子类中定义了与父类有相同名称和参数的方法时,子类对象使用该方法会调用子类中的定义。


15. forward(转发)和redirect(重定向)的区别


forward 是 服务器请求资源 ,服务器访问目标URL,把响应内容发给用户,用户不知道数据是从哪来的。

redirect 是 服务器向客户端发送一个状态码,告知重新请求该URL 。


16. 连接池的工作机制


服务器 启动时会建立一定数量的池连接 ,客户端需要连接时,池会 返回一个未使用的连接并将其标记为忙 ,如果没有空闲连接,池会

新建一定数量的连接 ,当连接使用完毕后,池会将其标记为空闲。


17. 什么是序列化


序列化就是一种 用来处理对象流的机制 ,就是 将对象的内容进行流化,可以对流化后的对象进行读写操作,也可以将流化后的对象传输于网络之间。

可通过实现 java.io.Serializable 接口来实现序列化。


二、第三方框架部分


1. 什么是AOP、Spring AOP的底层原理是什么


AOP是 面向切面编程 ,用于 在不改变原有逻辑的基础上增加一些额外的功能 ,如事务管理、日志、缓存、权限控制等。

Spring AOP是 基于代理 的。

如果目标对象 实现了接口 ,则默认采用 JDK动态代理 。

如果目标对象 没有实现接口 ,则采用 CgLib进行动态代理 。

如果目标对象实现了接口,且 强制CgLib 代理,则采用CgLib动态代理。


2. 什么是IOC、IOC注入方式有哪些


IOC翻译为 控制反转 ,他还有个别名为DI( 依赖注入 )。

IOC就是由IOC容器来 负责对象的生命周期和对象之间的关系 。

控制反转就是 本来应该你做的事情,让系统去做 ,比如通常获取一个对象需要通过new,而使用IOC则是IOC将对象创建后注入到被注入的对象中。

注解注入 (Spring)、 构造器注入 、 setter方法注入 、接口方式注入(不推荐)


3. Mybatis中 #{} 和 ${}的区别


#{}是 预编译 ,可 防止SQL注入 。

${}是直接 拼接 在SQL语句中。


4. Spring Boot的核心注解是什么,它是由哪几个注解组成的


核心注解: @SpringBootApplication

包含:

@SpringBootConfiguration 实现配置文件功能

@EnableAutoConfiguration 打开自动配置功能

@CompoentScan 组件扫描功能


5. SpringBoot 怎么读取配置文件


属性上使用@Value注解

类上使用@ConfigurationProperties注解

读取指定文件注解可在类上使用@PropertySource(不支持yml文件读取)

注入Environment对象获取到。


6. SpringCloud和Dubbo的区别


SpringCloud采用基于HTTP的 REST API ,Dubbo采用 RPC 方式。


7. SpringCloud的Hystrix断路器特性


请求熔断

:请求服务失败量超过一定比例(默认50%)断路器会切换到开路状态,这时所有请求不会发送到后端服务,断路器在保持开路状态一段时间后(默认5秒),自动切换到半开路状态。这时如果下一次请求成功,断路器切回闭路状态,否则重新切换到开路状态。

服务降级 :对于查询操作,可以实现一个fallback方法。当请求服务出现异常时,可以使用fallback方法返回的值。

依赖隔离

:通过线程池来实现资源隔离,比如一个服务调用另外两个服务,如果这两个服务在同一线程池,那么如果一个服务卡住,后面的请求又来了,就会导致后面的请求都会卡住等待。

请求缓存 :缓存上次请求结果,返回给后续请求。

请求合并 :把多个请求合并成一个请求,提升效率。


三、MySQL数据库部分


1. 事物的四大特性和隔离级别


原子性 :不可分割的操作单元,要么全部成功,要么回滚。

一致性 :如果执行事物之前数据库是一致的,那么执行后还是一致的。

隔离性 :事物操作之间彼此独立和透明,互不影响。

持久性 :事物一旦提交,其结果就是永久的。

未提交读 :允许脏读,其他事物只要修改了数据,即使未提交,本事物也能看到修改后的数据值。

提交读 :只能读取到已提交的数据。

可重复读 (innoDB默认):无论其他事物是否修改并提交了数据,这个事物中的数据不受影响。

串行读 :完全串行化的读,每次读都要获得锁,读写相互都会阻塞。


2. MySQL优化相关


使用更小的整数类型 、尽可能的 定义字段为not null (否则会导致索引复杂)、

只创建需要的索引、分库分表。

使用explain检查复杂SQL语句、LIMIT语句尽量要跟order by或distinct、

插入多条数据时使用单条INSERT语句。


3. MySQL存储引擎InnoDB和MyISAM的区别


InnoDB支持 事物 ,MyISAM不支持。

InnoDB支持 外键 ,MyISAM不支持。

InnoDB是 聚集索引 ,MyISAM是非聚集索引。索引和数据文件是分离的。

InnoDB必须要有 主键 (没有会自己找或创建),MyISAM可以没有。

InnoDB不保存表的行数,MyISAM用了一个变量保存表的行数。

InnoDB支持表、行级锁 默认行级锁,MyISAM只支持表级锁。


4. MySQL在哪些情况下不使用索引


like查询 使用%开头不能使用索引 ,但用%结尾的可以使用索引。

where语句中使用<>或!=。

where语句中使用or,且没有把or中的所有字段加上索引。

where语句中对字段表达式操作。

where语句中使用NOT IN。使用简单的IN会使用索引。


5. MySQL分库分表策略


垂直切分 :某个表字段过多,可以 将不常用或字段长度较大的字段拆分出去到扩展表 中。

水平切分 :分为库内分表和分库分表,是根据表内数据的逻辑关系, 按照不同的条件分散到多个数据库或表 中。


四、扩展阅读


1. 关于Spring对JDK和CgLib动态代理的选择


通过查阅Spring-AOP包中的org.springframework.aop.framework.DefaultAopProxyFactory

类得到以下代码:


public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
  @Override
  public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      Class<?> targetClass = config.getTargetClass();
      if (targetClass == null) {
        throw new AopConfigException("TargetSource cannot determine target class: " +
            "Either an interface or a target is required for proxy creation.");
      }
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
        return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
    }
    else {
      return new JdkDynamicAopProxy(config);
    }
  }
  private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
    Class<?>[] ifcs = config.getProxiedInterfaces();
    return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
  }
}

可以看到,Spring先使用isOptimize()方法、isProxyTargetClass()方法以及hasNoUserSuppliedProxyInterfaces()方法进行判断,这三个方法的含义分别如下:


isOptimize()


是否对生成代理策略进行优化

当返回值为true时为进行优化,如果有接口就代理接口(使用JDK动态代理),没有接口代理类(CGLIB代理)

当返回值为false时为不进行优化(default)


isProxyTargetClass()


是否强制使用CGLIB来实现代理

当返回值为true时为强制使用CgLib来实现代理

当范围值为false时为不强制使用CgLib来实现代理,而是首选JDK来实现代理(default)


hasNoUserSuppliedProxyInterfaces()


判断代理的对象是否只有指定了SpringProxy的接口或未实现接口

当返回值为true时代表没有实现接口或仅实现了指定SpringProxy的接口

当返回值为false时代表实现了接口,直接使用JDK动态代理


当了解这三个方法的含义后,接下来阅读代码就很简单了。

如果以上三个方法有任意方法返回值为true,就进入下一步判断,如果所有的返回值均为false,说明即不强制使用CgLib,或又实现了接口,则使用JDK动态代理。

在第二步判断中,首先对其targetClass进行了判空,然后判断它是否为接口或代理类,如果是则使用JDK动态代理。

反之,则使用CgLib进行代理。


2. 为什么CgLib可以代理任何类,但还是需要JDK的动态代理?CgLib和JDK动态代理的区别。


这就不得不说到CgLib的特点:创建速度慢但执行速度快,而JDK的动态代理与其刚好相反:创建速度快但执行速度慢。

如果在程序运行时不断地使用CgLib去创建代理的话,系统运行的性能会大打折扣,所以建议一般在系统初始化时采用CgLib来创建代理,并放入Spring的ApplicationContext中。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
71 2
|
21天前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
53 14
|
1月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
1月前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
1月前
|
存储 缓存 Oracle
Java I/O流面试之道
NIO的出现在于提高IO的速度,它相比传统的输入/输出流速度更快。NIO通过管道Channel和缓冲器Buffer来处理数据,可以把管道当成一个矿藏,缓冲器就是矿藏里的卡车。程序通过管道里的缓冲器进行数据交互,而不直接处理数据。程序要么从缓冲器获取数据,要么输入数据到缓冲器。
Java I/O流面试之道
|
25天前
|
Java 编译器 程序员
Java面试高频题:用最优解法算出2乘以8!
本文探讨了面试中一个看似简单的数学问题——如何高效计算2×8。从直接使用乘法、位运算优化、编译器优化、加法实现到大整数场景下的处理,全面解析了不同方法的原理和适用场景,帮助读者深入理解计算效率优化的重要性。
30 6
|
1月前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
57 4
|
1月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
114 4
|
2月前
|
存储 安全 算法
Java面试题之Java集合面试题 50道(带答案)
这篇文章提供了50道Java集合框架的面试题及其答案,涵盖了集合的基础知识、底层数据结构、不同集合类的特点和用法,以及一些高级主题如并发集合的使用。
116 1
Java面试题之Java集合面试题 50道(带答案)
|
2月前
|
存储 Java 程序员
Java面试加分点!一文读懂HashMap底层实现与扩容机制
本文详细解析了Java中经典的HashMap数据结构,包括其底层实现、扩容机制、put和查找过程、哈希函数以及JDK 1.7与1.8的差异。通过数组、链表和红黑树的组合,HashMap实现了高效的键值对存储与检索。文章还介绍了HashMap在不同版本中的优化,帮助读者更好地理解和应用这一重要工具。
66 5
下一篇
DataWorks