一、Java基础 Java 17中的sealed类和record类的作用和区别?
答案:sealed类:限制继承关系,通过permits指定允许的子类。
示例代码:
public sealed class Shape permits Circle, Square { ... }
;record类:不可变数据类,自动生成equals()、hashCode()和toString()。示例代码:public record User(String name, int age) { }
String、StringBuffer和StringBuilder的区别? 答案: | 类 | 可变性 | 线程安全 | 性能 | | --- | --- | --- | --- | | String | 不可变 | 安全 | 低 | | StringBuffer | 可变 | 安全 | 中(同步) | | StringBuilder | 可变 | 不安全 | 高 |
equals()和==的区别?如何重写equals()? 答案:==:比较对象内存地址(基本类型比较值)。equals():默认同==,可重写为逻辑相等(如字符串内容)。重写需满足:自反性、对称性、传递性、一致性。始终重写hashCode()以保证哈希一致性。
什么是B/S架构?什么是C/S架构 答案:B/S(Browser/Server),浏览器/服务器程序;C/S(Client/Server),客户端/服务端,桌面应用程序。
你所知道网络协议有那些? 答案:HTTP:超文本传输协议;FTP:文件传输协议;SMPT:简单邮件协议;TELNET:远程终端协议;POP3:邮件读取协议。
Java都有那些开发平台? 答案:JAVA SE:主要用在客户端开发;JAVA EE:主要用在web应用程序开发;JAVA ME:主要用在嵌入式应用程序开发。
什么是JVM?java虚拟机包括什么? 答案:JVM:java虚拟机,运用硬件或软件手段实现的虚拟的计算机,Java虚拟机包括:寄存器,堆栈,处理器。
Java是否需要开发人员回收内存垃圾吗? 答案:大多情况下是不需要的。Java提供了一个系统级的线程来跟踪内存分配,不再使用的内存区将会自动回收。
什么是JDK?什么是JRE? 答案:JDK:java development kit,java开发工具包,是开发人员所需要安装的环境;JRE:java runtime environment,java运行环境,java程序运行所需要安装的环境。
什么是数据结构? 答案:计算机保存,组织数据的方式。
Java的数据结构有那些? 答案:线性表(ArrayList)、链表(LinkedList)、栈(Stack)、队列(Queue)、图(Map)、树(Tree)。
什么是OOP? 答案:面向对象编程。
什么是面向对象? 答案:世间万物都可以看成一个对象。每个物体包括动态的行为和静态的属性,这些就构成了一个对象。
类与对象的关系? 答案:类是对象的抽象,对象是类的具体,类是对象的模板,对象是类的实例。
Java中有几种数据类型 答案:整形:byte,short,int,long;浮点型:float,double;字符型:char;布尔型:boolean。
什么是隐式转换,什么是显式转换 答案:显示转换就是类型强转,把一个大类型的数据强制赋值给小类型的数据;隐式转换就是大范围的变量能够接受小范围的数据;隐式转换和显式转换其实就是自动类型转换和强制类型转换。
Char类型能不能转成int类型?能不能转化成string类型,能不能转成double类型 答案:Char在java中也是比较特殊的类型,它的int值从1开始,一共有2的16次方个数据;Char<int<long<float<double;Char类型可以隐式转成int,double类型,但是不能隐式转换成string;如果char类型转成byte,short类型的时候,需要强转。
什么是拆装箱? 答案:拆箱:把包装类型转成基本数据类型;装箱:把基本数据类型转成包装类型。 Java中的包装类都是那些? 答案:byte:Byte;short:Short;int:Integer;long:Long;float:Float;double:Double;char:Character;boolean:Boolean。
一个java类中包含那些内容? 答案:属性、方法、内部类、构造方法、代码块。
例如: if(a+1.0=4.0),这样做好吗? 答案:不好,因为计算机在浮点型数据运算的时候,会有误差,尽量在布尔表达式中不使用浮点型数据(if,while,switch中判断条件不使用浮点型)。
那针对浮点型数据运算出现的误差的问题,你怎么解决? 答案:使用Bigdecimal类进行浮点型数据的运算。
++i与i++的区别 答案:++i:先赋值,后计算;i++:先计算,后赋值。
程序的结构有那些? 答案:顺序结构、选择结构、循环结构。
数组实例化有几种方式? 答案:静态实例化:创建数组的时候已经指定数组中的元素,如int[] a = new int[]{1,3,3};动态实例化:实例化数组的时候,只指定了数组程度,数组中所有元素都是数组类型的默认值。
Java中各种数据默认值 答案:Byte、short、int、long默认是都是0;Boolean默认值是false;Char类型的默认值是'';Float与double类型的默认是0.0;对象类型的默认值是null。
Java常用包有那些? 答案:Java.lang、Java.io、Java.sql、Java.util、Java.awt、Java.net、Java.math。
Java最顶级的父类是哪个? 答案:Object。
Object类常用方法有那些? 答案:Equals、Hashcode、toString、wait、notify、clone、getClass。
java中有没有指针? 答案:有指针,但是隐藏了,开发人员无法直接操作指针,由jvm来操作指针。
java中是值传递引用传递? 答案:理论上说,java都是引用传递,对于基本数据类型,传递是值的副本,而不是值本身。对于对象类型,传递是对象的引用,当在一个方法操作操作参数的时候,其实操作的是引用所指向的对象。
假设把实例化的数组的变量当成方法参数,当方法执行的时候改变了数组内的元素,那么在方法外,数组元素有发生改变吗? 答案:改变了,因为传递是对象的引用,操作的是引用所指向的对象。
实例化数组后,能不能改变数组长度呢? 答案:不能,数组一旦实例化,它的长度就是固定的。
假设数组内有5个元素,如果对数组进行反序,该如何做? 答案:创建一个新数组,从后到前循环遍历每个元素,将取出的元素依次顺序放入新数组中。
形参与实参 答案:形参是方法定义时的参数,实参是方法调用时传递的参数。
Java中的泛型是什么?它有什么作用? 答案:Java中的泛型是一种参数化类型,它允许使用一个占位符来代表各种类型。它的作用是在编译时检测类型的一致性,避免了类型转换错误,并提高了代码的重用性。
Java中的类和对象有什么区别? 答案:类是描述对象的模板,对象是类的实例。类定义了对象的属性和行为,而对象则具体地拥有这些属性和行为。
Java中的封装是什么?它有什么作用? 答案:封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。封装可以隐藏内部细节,提供对外部的安全接口,并实现代码的重用和维护。
Java是否支持多继承?如果不支持,它是如何实现类似功能的? 答案:Java不支持多继承,一个类只能继承一个父类。但是Java支持接口的多实现,实现了多继承的效果。
Java中的构造方法有什么作用? 答案:构造方法是用于在创建对象时初始化对象的状态。它的名称与类名相同,没有返回类型。
接口的意义是什么? 答案:接口的意义可以用三个词来概括:规范、扩展、回调。接口定义了一组方法的规范,实现接口的类必须遵守这些规范。接口可以作为类型使用,实现多态性。接口还可以用于实现回调机制。
Java中的异常处理机制是怎样的? 答案:Java中的异常处理机制通过try-catch-finally语句块实现。try块中放置可能抛出异常的代码,catch块用于捕获并处理异常,finally块则无论是否发生异常都会执行。
Java中的集合框架是什么?它包含哪些主要的接口和类? 答案:Java集合框架是一个为表示和操作集合而设计的统一架构,它包含了List、Set、Queue和Map等主要接口,以及ArrayList、LinkedList、HashSet、HashMap等实现类。
Java中的线程状态有哪些? 答案:Java中的线程状态主要有五种:新建(NEW)、就绪(RUNNABLE)、阻塞(BLOCKED)、等待(WAITING)、超时等待(TIMED_WAITING)和终止(TERMINATED)。
什么是Java中的线程同步?如何实现? 答案:线程同步是多个线程之间访问共享资源时的一种协调机制,它保证了在并发环境下,对共享资源的访问是有序和一致的。Java中可以通过synchronized关键字或Lock接口实现线程同步。
Java中的垃圾回收机制是怎样的? 答案:Java中的垃圾回收机制自动管理内存,当对象不再被引用时,垃圾回收器会自动回收其占用的内存。Java程序员无需手动释放内存。
什么是Java中的反射机制?它有哪些应用场景? 答案:反射机制是指在运行时能够获取类的信息并动态地调用类的方法或属性。Java中的反射机制通过Class类实现。反射机制为Java程序提供了强大的动态性。通过反射,程序可以在运行时加载类、创建对象、调用方法等。这使得Java程序能够更加灵活地应对各种复杂场景,如框架设计、插件机制等。
什么是Java中的内部类?它有哪些种类? 答案:Java中的内部类是指定义在一个类内部的类。它主要有四种类型:静态内部类、成员内部类、局部内部类和匿名内部类。
Java中的枚举类型是什么?它有哪些特点? 答案:Java中的枚举类型是一种特殊的类,用于表示固定数量的常量值。枚举类型具有类型安全、易于理解和使用的特点。
Java中的泛型擦除是什么?它有哪些影响? 答案:泛型擦除是指在编译期间,Java编译器将泛型信息擦除,生成没有泛型信息的字节码文件。泛型擦除是Java泛型实现的一种方式。
数据库事务特性。原子性、一致性、隔离性、持久性
如何防止SQL注入:使用#不要使用$符号;对所有的入参做校验;使用存储过程;执行预处理语句和参数化查询;最低权限原则;
微服务拆分的原则:微服务的拆分应该从业务、技术、组织结构三个维度进行考虑。业务上按照DDD领域驱动设计原则来进行拆分,然后根据持续演进原则先粗后细逐步的进行迭代。
技术上按照单一责任、闭包、服务自治、高内聚低耦合、数据隔离原则进行拆分,也需要考虑性能问题将性能要求高或性能压力大的服务单拆出来,比如流量较大的服务可以做读写分离。
还需要考虑稳定性原则,将成熟改动不大的服务拆分为稳定服务,避免频繁发布,改动多业务迭代快的拆分为变动服务。还可以根据安全隔离进行拆分,区分为对外的跟对内的。还要对重复功能进行沉淀,沉淀为通用服务避免重复造轮子。还有不同语言的可以异构成独立服务。
组织上,根据公司的组织结构来设计,按照康威定律
拆分完如何验证合理性:还是要从业务、技术、组织结构上来评估合理性,业务上能不能满足当前跟未来的发展;技术上性能、安全性、部署维护成本;组织上是不是促进团队协作跟沟通。微服务的拆分跟合并是一个持续演进的过程,需要不断的迭代优化。
kafka为什么支持高吞吐。
分区分段与并行处理。topic分成多个分区,不同分区在不同服务器上,还对数据进行分段分段之后再加索引,生产者消费者并行处理。
批量读写、批量压缩
直接用系统的page Cache,读写都基于内存。又使用了零copy技术直接将数据copy到nic缓冲区,减少数据在用户空间跟内核空间复制。
顺序写磁盘技术。减少磁盘寻址时间,当然带来的问题就是不能删数据 使用kafka如何避免消息丢失。
生产者使用ack机制,0消息发出就算成功、1broker的Leader副本收到就算成功、-1Leader跟follower都写入成功;
broker是异步刷盘也有可能失败,但是设置了一个分区几个副本,设置刷盘频率 消费者这边设置提交offset的机制,关闭自动提交消费完成之后再提交,支持幂等消费 数据库三范式。原子性、唯一性、冗余性
MySQL优化。
连接数优化。增加最大连接数、修改默认超时时间释放不活跃的连接,但不要释放连接池;客户端连接池的合理利用 集群优化,读写分离,分库分表,垂直分库水平分表
打开慢查询日志,分析慢查询情况
优化SQL语句,通过explain 执行计划,创建合适的索引,唯一索引、普通索引、复合索引。SQL语句优化,不在索引列使用函数,不在where语句上使用操作符,不在where上进行null判断,不在where使用or来连接条件,模糊查询%在后面。查询多行一定要分页;尽量用连接查询代替子查询
怎么排查Java程序占用CPU过高。
JPS查看本机线程信息。
top命令找到占用最高的进程PID, 在用(top -hp PID)查看进程下的线程ID转换为16进制线程ID TID(printf"%x\n" tid), jstack打印线程堆栈。jstack PID命令生成Java进程的线程快照,在快照里面通过TID找到堆栈(jstack pid | grep tid -A 60)
Jstat监控JVM内存。如果gc过高继续用 jstat -gc pid 3000,如果fgc频率高就用jstack跟jmap分析堆内存使用情况
Jmap生成内存快照。用jmap -dump:format=b,file=heapdump.phrof pid命令去生成dump文件然后用专用软件如jprofiler
常用的设计模式
单例、工厂、适配器、观察者、建造者、策略模式、责任链、代理模式
synchronized和Lock的区别
synchronized:Java关键字,jvm层面实现的隐式锁不需要自己释放,可以加在方法或者代码块,可重入不可中断非公平锁。低竞争模式下性能好,因为使用了CPU的悲观锁,并且排它锁第二个线程获取不到锁会一直等待。偏向锁、轻量级锁、重量级锁
Lock:是一个类,需要自己手动释放,可重入可中断可以是公平锁也可以非公平,高并发时候性能好,因为是乐观锁,AQS+CAS实现的,AQS就是维护锁状态跟先进先出队列,CAS是硬件级别的原子操作会尝试更新锁状态。
线程池
FixedThreadPool,固定大小线程池,比如查询数据库,阻塞队列 SingleThreadExecutor,单线程,比如处理文件读写,阻塞队列 CachedThreadPool,动态线程池 ScheduledThreadPool,定时执行的线程池 实际使用中自己通过ThreadPoolExecutor创建线程,CPU密集型任务比如视频解码数据加密,核心线程数跟最大线程都可以是CPU线程数+1,线程超过CPU核心数增加上下文切换开销,额外一个线程是因为某线程因为页缺失等原因阻塞时可以继续利用CPU。IO密集型任务可以配置CPU的2倍,最大线程可以设置2~3倍
thrift
支持二进制跟文本传输协议,支持基本类型、结构体、集合、异常类型、服务类型,底层是RPC远程调用,定义好协议格式,主要是数字
char 跟 varchar区别 char,固定长度适合保存手机号、身份证号等定长数据, varchar,可变长度,适合存name、地址信息,多一位存储长度 MySQL数据库索引
通过B+树存储,叶子结点存放key跟value,其他节点存放key,叶子结点有引用指向相邻的叶子节点。数据量增加、插入删除数据时会进行重平衡,
SynchronizedMap 使用分段锁保证性能,一次锁住一个桶默认16个桶,jdk8之后也改用CAS(Compare And Swap)
并发编程三要素
原子性、有序性、可见性 CyclicBarrier 和 CountDownLatch 的区别
count 是线程等待其他线程都执行完当前线程才继续执行,定时任务中并行计算结果出来之后统一处理,计数器只能用一次, cyclicBarrier 是所有线程都进入await方法后同时执行, 计数器可以reset,处理复杂场景比如计算错误再来一遍
技术难点 如何让上游无感知迁移流量。在原有SDK接口上面增加一个切面吧流量拿到改成调用服务B;处理蜂窝刷新问题,将门店切成10份分散执行,执行中使用线程池并行计算,拿到结果再批量入库。
JVM内存 堆、方法区是线程共享,虚拟机栈、本地方法栈、程序计数器是线程独有。垃圾回收主要针对堆,堆主要存放new出来的对象(方法中对象引用没有被返回或没有在方法体外被使用),新生代(eden、from suvivor、to suvivor)、老年代。方法区之前存在永久代8之后被元空间替代,永久代有内存溢出风险、垃圾回收效率低、无法动态调整大小、无法回收常量池中的内存。元空间存储在本地内存不在jvm,突破内存限制减少OOM,可以动态调整大小。缺点也可能内存溢出、需要重新考虑内存管理和调优 Sping事务失效
数据库引擎不支持;没有被Spring管理;非public方法(通过AspectJ代理模式也可以)或者方法被final、static修饰;是否是自调用情况;数据源没配置事务管理器;异常被吞掉没有正确抛出或者抛出的异常类型错误;多线程 ES深分页怎么解决
Scroll API 适合遍历大量数据,他像一个游标会生成快照,后续分页都按照快照避免了重复排序的开销,适合需要大量遍历数据的场景;Search After 5.0之后引入的分页方式,会基于上一个分页最后一条记录的排序值进行下一个分页查询,避免from + size带来的开销。适合实时分页场景。
Scroll API的快照有啥问题
新数据写入或者已有数据删除、更新这些变化不会反应在快照中,查询结果不实时;维护快照占用内存资源多;适合一次性批量导出数据,不适合实时交互的分页查询;Scroll Id 游标存在过期问题默认5分钟 二、并发编程
-
synchronized和ReentrantLock的底层实现差异? 答案:synchronized:JVM层面通过monitorenter和monitorexit指令实现,依赖对象头中的Mark Word。ReentrantLock:基于AQS(AbstractQueuedSynchronizer),通过CAS和CLH队列实现锁竞争,支持公平锁和非公平锁。 -
ThreadLocal的原理和内存泄漏问题如何避免? 答案:原理 :每个线程持有独立的ThreadLocalMap,Key为弱引用的ThreadLocal对象。内存泄漏 :Key被回收后,Value仍被强引用,需调用remove()手动清理。 -
如何实现高并发下的无锁编程? 答案:使用
Atomic类(如AtomicInteger)的CAS操作;基于Unsafe类直接操作内存;JDK 8+的LongAdder替代AtomicLong,减少CAS竞争。 -
Java中实现多线程有几种方法 答案:继承
Thread类;实现Runnable接口;ExecutorSenvice、Callable、Future有返回值线程;基于线程池的方式。 -
如何停止一个正在运行的线程 答案:可以使用
interrupt()方法中断线程,但需要在线程内部处理中断信号;也可以通过设置标志位来控制线程的运行。 -
notify()和notifyAll()有什么区别? 答案:notify()随机唤醒一个在该对象上等待的线程;notifyAll()唤醒所有在该对象上等待的线程。 -
sleep()和wait()有什么区别? 答案:sleep()是Thread类的方法,会让当前线程暂停执行指定的时间,不会释放对象的锁;wait()是Object类的方法,会让当前线程进入等待状态,同时释放对象的锁,直到其他线程调用notify()或notifyAll()方法唤醒它。 -
volatile是什么?可以保证有序性吗? 答案:volatile是一个关键字,用于修饰变量,保证变量的可见性,即当一个变量被声明为volatile时,它会保证对该变量的写操作会立即刷新到主内存中,而读操作会从主内存中读取最新的值。volatile不能保证变量操作的原子性和有序性。 -
Thread类中的start()和run()方法有什么区别? 答案:start()方法用于启动一个新线程,它会调用run()方法;run()方法是线程的执行体,包含了线程要执行的代码。如果直接调用run()方法,并不会启动新线程,而是在当前线程中执行run()方法中的代码。 -
为什么
wait,notify和notifyAll这些方法不在thread类里面? 答案:wait,notify和notifyAll是Object类的方法,因为这些方法是用于线程间的通信和同步,而对象是线程间共享的资源,所以这些方法定义在Object类中,以便所有对象都可以使用。 -
为什么
wait和notify方法要在同步块中调用? 答案:wait和notify方法用于线程间的同步和通信,必须在同步块中调用,因为在调用这些方法时,线程必须持有对象的锁。如果不在同步块中调用,会抛出IllegalMonitorStateException异常。 -
Java中
interrupted()和isInterrupted()方法的区别? 答案:interrupted()是一个静态方法,它会检查当前线程的中断状态,并清除中断标志;isInterrupted()是一个实例方法,它会检查调用该方法的线程的中断状态,但不会清除中断标志。 -
Java中
synchronized和ReentrantLock有什么不同? 答案:synchronized是Java的关键字,是JVM层面的实现,使用简单,自动释放锁;ReentrantLock是一个类,是基于AQS实现的,功能更强大,如支持公平锁、可中断锁、条件变量等,但需要手动释放锁。 三、JVM JVM内存模型(JMM)与硬件内存模型的联系? 答案:JMM :定义线程与主内存的交互规则(如volatile的可见性、synchronized的原子性)。硬件模型 :通过CPU缓存一致性协议(如MESI)实现内存可见性。 G1垃圾回收器的工作流程? 答案:初始标记(STW) :标记GC Roots直接关联对象;并发标记 :遍历对象图;最终标记(STW) :处理SATB(Snapshot-At-The-Beginning)记录;筛选回收 :按Region回收垃圾,优先回收价值高的Region。 如何排查OOM(OutOfMemoryError)? 答案:使用-XX:+HeapDumpOnOutOfMemoryError生成堆转储文件;通过MAT或VisualVM分析堆转储,定位大对象或内存泄漏;检查代码中的静态集合、未关闭资源、缓存策略。 四、框架(Spring/Spring Boot) -
Spring Bean的生命周期? 答案:实例化 → 属性填充 →
BeanNameAware→BeanFactoryAware→ApplicationContextAware→PostConstruct→InitializingBean→ 自定义init方法 → 使用 →PreDestroy→DisposableBean→ 自定义destroy方法。 -
Spring Boot自动配置的实现原理? 答案:通过
@EnableAutoConfiguration加载META-INF/spring.factories中的配置类;利用条件注解(如@ConditionalOnClass)按需加载Bean。 -
Spring事务失效的常见场景? 答案:方法非
public→ 事务注解不生效;自调用(同一类中调用带@Transactional的方法)→ 代理失效;异常未被抛出或捕获后未回滚 → 需配置rollbackFor。 -
Spring框架中IOC和AOP的概念和作用? 答案:IOC(Inversion of Control)即控制反转,是一种设计思想,将对象的创建和依赖关系的管理交给Spring容器,而不是由对象本身来管理。IOC的作用是降低对象之间的耦合度,提高代码的可维护性和可测试性。AOP(Aspect Oriented Programming)即面向切面编程,是一种编程范式,通过将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高代码的复用性和可维护性。
-
Spring中Bean的作用域有哪些? 答案:Spring中Bean的作用域主要有以下几种:
-
singleton:单例模式,Spring容器中只会创建一个Bean实例。 -
prototype:原型模式,每次从Spring容器中获取Bean时,都会创建一个新的实例。 -
request:在一次HTTP请求中,只会创建一个Bean实例。 -
session:在一个HTTP会话中,只会创建一个Bean实例。 -
global session:在全局会话中,只会创建一个Bean实例
这不止是一份试题清单,更是一种“被期望的责任”,因为有无数个想收到大厂offer的人了,希望您能把这篇文章分享给更多的朋友,让它帮助更多的人帮助他人,快乐自己,最后,感谢您的阅读。