「年底备战」Java 高级面试题之Java基础(附答案详解)
qihemm 2025-06-15 20:44 31 浏览 0 评论
前言
好哥哥们,Redis系列文章可能会先不弄了,目前的话写到了第二十四篇深入理解 Redis 主从复制,有感兴趣的好哥哥可以翻翻这个系列的文章(看完记得点赞加关注哟)。后面的话应该是会整理一些面试相关的,主要的话是我自己也有很多东西都不记得了,趁这个机会好好捡起来,也属于年底备战吧。然后的话这个是持续更新的,有感兴趣的面试题可以在评论留言,会的我就加进来,不会的我百度加进来(狗头保命)。
1. JAVA 中面向对象的特征有哪些?
主要有四大特性:封装、继承、多态、抽象(很多人也认为只有三大特性)
封装
封装的思想保证了类内部数据结构的完整性,使用户无法轻易直接操作类的内部数据,这样降低了对内部数据的影响,提高了程序的安全性和可维护性。
优点:
- 只能通过规定方法访问数据。
- 隐藏类数实现细节。
- 方便修改实现。
- 方便加入控制语句。
继承
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或类从父 类继承方法,使得子类具有父类相同的行为。
还有一个地方需要知道的是,这里还有一个概念叫做组合,可以在面试的时候提一下。组合其实很简单,就是单纯的将某个对象引入当前类,让当前类有引入类的功能,因为 JAVA 只能单继承,所以某些场景下组合其实更合适。
特点:
- 继承父类的重用。
- 继承可以多层继承。
- 一个类只能继承一个父类。
- 父类中private修饰的不能被继承。
- 构造方法不能被继承。
多态
多态是同一个行为具有多个不同表现形式或形态的能力。产生的场景是将子类对象赋给父类的引用,会产生多态。如:Father son = new Son() 此时的对象son只能调用Father的方法(指的是子类重写或者继承父类的那些方法),而不能调用本身定义的一些方法。因为多态中强调:编写 java 程序时,引用类型变量只能调用其编译时类型的变量,不能调用其运行时类型变量。
特点:
- 继承父类的重用。
- 继承可以多层继承。
- 一个类只能继承一个父类。
- 父类中 private 修饰的不能被继承。
- 构造方法不能被继承。
必要条件 : 继承、重写、父类引用指向子类对象。
作用:
- 不必编写每一子类的功能调用,可以直接把不同子类当父类看,屏蔽子类间的差异(也可以说隐藏了细节),提高代码的通用率/复用率。
- 父类引用可以调用不同子类的功能,提高了代码的扩充性和可维护性。
抽象
用 abstract 关键字来修饰一个类时,这个类叫作抽象类。抽象类是它的所有子类的公共属性的集合,是包含一个或多个抽象方法的类。但不意味着抽象类中只能有抽象方法,它和普通类一样,可以拥有普通的成员变量、方法。
特点:
- 抽象类不能被实例化。抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
- 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
- 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
- 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
- 被定义为 abstract 的类需要被子类继承,但是被修饰为final的类是不能被继承和改写的,这两者是不能一起用来做修饰的。
2. JAVA 中的基本数据类型有哪些,对应的大小和包装类型是什么?
八种基本数据类型: int、short、float、double、long、boolean、byte、char。
封装类分别是: Integer、Short、Float、Double、Long、Boolean、Byte、Character。
大小分别是(byte): int:4、short:2、float:4、double:8、long:8、boolean:1、byte:1、char:2。
3. Java 的引用类型有哪些?
一共有四种引用,分别是强引用、软引用(SoftReference)、弱引用(WeakReference)、虚引用(PhantomReference)。
- 强引用
最普遍的一种引用方式。如 String s = "abc", 变量 s 就是字符串abc的强引用。只要强引用存在,则垃圾回收器就不会回收这个对象。 - 软引用(SoftReference.java)
用于描述还有用但非必须的对象,如果内存足够,不回收,如果内存不足,则回收。一般用于实现内存敏感的高速缓存,软引用可以和引用队列 ReferenceQueue 联合使用,如果软引用的对象被垃圾回收,JVM 就会把这个软引用加入到与之关联的引用队列中。 - 弱引用(WeakReference.java)
弱引用和软引用大致相同,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。 - 虚引用(PhantomReference.java)
就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。
4. String、StringBuffer 和 StringBuilder 的区别有哪些?
String
String 是一个不可变(值是不可变的)的类对象,这就导致每次对String 的操作都会生成新的String对象,在操作频繁的场景中可能会出现性能问题和内存溢出的情况。
StringBuffer
StringBuffer 是一个值可变的类对象,内部维护的是字符数组。另外 StringBuffer 是线程安全的,因为StringBuffer所有 public 方法都是 synchronized 修饰的。这也就会导致在数据量大的情况下的性能问题。
StringBuilder
StringBuilder 和StringBuffer 是一样的,都是字符串变量。区别在于StringBuilder的方法都没有加synchronized 修饰。所以在性能上要优于 StringBuffer ,但是StringBuilder在多线程环境下不是线程安全的。
5. 能说说进程和线程的区别吗?
每次问到能说说这种类型的问题时,我真想说一句不能。
进程
进程指的是在系统中正在运行的一个应用程序。程序一旦运行就是进程,进程是资源分配的最小单位。
线程
线程是系统分配处理器时间资源的基本单元,是程序执行的最小单位。或者说进程内独立执行的一个单元执行流。
栗子
比如我们平常用的微信其实就是一个进程。而像微信中的朋友圈、扫一扫等功能就可以理解成为一个个单独的线程。
6. 你们平时是怎么创建线程的,还有其他的方式吗?
- 通过实现Runnable接口,将Runnable实现类当成参数来创建线程类。
- 通过继承Thread类创建线程类(重写run方法)。
- 通过实现Callable和Future创建线程(可以获取线程的返回值)。
7. Thread 类中的 start 和 run 方法有什么区别?
start方法被用来启动新创建的线程,而run一般是线程对应的业务逻辑。
另一方面start方法内部调用了run方法,这和直接调用run方法的效果不一样。当你调用run方法的时候,只会是在原来的线程中调用,没有新的线程启动,start方法才会启动新线程。
8. 线程池用过吗,原理是什么?
用过的,由于频繁的创建和销毁线程一方面会增加对系统资源的消耗,另一方面,会影响程序的性能。在处理多任务的场景下,可以使用池化技术将创建和销毁这过程给省略掉。 在 Java 中,常见的线程池有newSingleThreadExecutor(单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行)、newFixedThreadPool(定长线程池,可控制线程最大并发数,超出的线程会在队列中等待)、newCachedThreadPool(可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程)、newScheduledThreadPool(定长线程池,支持定时及周期性任务执行)。
原理
这个的话个人认为把整个线程池执行的过程讲清楚就可以了,当然可以先把创建线程池的线程池的七个参数讲一下(上面几个常用的线程池也是通过指定默认的几个参数来创建的)。
- maximumPoolSize 最大线程数。
- corePoolSize核心线程数。
- keepAliveTime线程活跃时间。
- TimeUnit线程活跃时间单位。
- workQueue阻塞队列。
- RejectedExecutionHandler拒绝策略。
- ThreadFactory 创建线程的工厂。
还是一样,自己根据对线程池的理解组织一下话术。
9. 那线程池的拒绝策略有哪些?
当线程池不能再创新的线程后(参考上图),线程池就会执行拒绝策略。拒绝策略主要有一下(当然排查自定义的策略, 如果有面试官问这个那还是问的比较深比较变态的):
- AbrtPolicy直接丢弃任务,抛出异常,这是默认策略。
- CallerRunsPolicy只用调用者所在的线程来处理任务。
- DiscardOldestPolicy丢弃等待队列中最旧的任务,并执行当前任务。
- DiscardPolicy直接丢弃任务,也不抛出异常。
10. 简单讲一下 wait 和 sleep 的区别?
waitsleep调用时机只能在同步上下文中调用,否则抛出
IllegalMonitorStateException异常不需要在同步上下文中调用作用对象定义在Object类中,作用于对象本身定义在Thread中,作用于当前线程释放资源被调用时释放锁资源被调不释放资源,当前线程阻塞唤醒方式调用notify、notifyAll或者超时调用interrupt或超时方法属性实例方法静态方法
11. volatile 关键字原理有了解过吗?
首先使用volatile声明的变量,可以确保值被更新的时候对其他线程立刻可见,并且可以防止指令重排序。
原理
这个问题的我会先回答上面的作用,然后在将一下MESI 协议 和 Java 的内存模型。至于指令重排的原理我会忽略性不讲。因为这一块东西太多了,扯下去的话时间会很久也比较难讲清楚。
MESI 协议
多核CPU 在读/写取数据的过程大致是CPU -> CPU缓存(L1、L2、L3) -> 内存,MESI(Modified、Exclusive、Shared、Invalid 首字母缩写) 协议就是用于保证这个过程中每个缓存中使用的共享变量的副本和内存中是一致的。当CPU写数据时,如果发现操作的变量是共享变量,先将变量设置为独占(Exclusive)状态,当进行设值操作是把变量状态设置为修改(Modified)状态,然后通过总线嗅探机制发出信号通知其他CPU将该变量的缓存行置为无效(Invalid)状态。设置完成后将变量状态修改为共享(Shared)。其他CPU需要读取这个变量时,会发现自己缓存中缓存该变量的缓存行是无效的(Invalid),那么它就会从内存重新读取。
volatile 原理
首先,Java 的内存模型(JMM)和上图基本思想是一致的。在JMM中同样也区分了主内存(主存)、线程副本(缓存)。当修改volatile变量时会强制将修改后的值刷新的主内存中。修改volatile变量后会导致其他线程工作内存中对应的变量值失效(与上面是一致的)。因此,再读取该变量值的时候就需要重新从读取主内存中的值(保证可见性)。
12. synchronized 的作用和原理能讲一讲吗?
synchronized 是 Java 中解决并发问题的一种最常用的方法,也是最简单的一种方法。synchronized的作用主要有三个:
- 确保线程互斥的访问同步代码。
- 保证共享变量的修改能够及时可见。
- 有效解决重排序问题。
原理
使用synchronized之后,通过编译后的字节码会发现在同步的代码块前后会加上monitorenter和monitorexit字节码指令,在同步方法中会添加ACC_SYNCHRONIZED 标记。然后在 Java 中每个对象都会有一个属于自己的监视器锁(monitor),执行monitorenter 指令(ACC_SYNCHRONIZED标记执行逻辑也是一样的)时就是尝试获取 monitor 所有权的过程。如果对象没有被锁定或者已经获得了锁(可重入性),锁的计数器 +1,此时其他竞争锁的线程则会进入等待队列中。
monitorexit 指令只能被持有 monitor 锁的线程执行。当monitorexit 指令被执行时,monitor 锁的计数器就会做-1操作。当计数器值为0时,则释放锁,并且唤醒处于等待队列中的线程再继续竞争锁。
13. synchronized 锁优化了解过吗?
在 JDK1.6 版本前,synchronized 锁是一把重量级锁。从JDK1.6版本之后,对synchronized 锁经过了一系列的优化。优化机制包括自适应锁、自旋锁、锁消除、锁粗化、轻量级锁和偏向锁。简单点来说就是使用synchronized 锁一开始会变成偏向锁而不是重量级锁,然后经过锁竞争会有一个从无锁->偏向锁->轻量级锁->重量级锁 的锁升级过程。
自旋锁
自旋锁主要发生在线程阻塞等待期间,由于大部分时候锁被占用的时间很短,共享变量的锁定时间也很短,所有没有必要挂起线程,用户态和内核态的来回上下文切换严重影响性能。自旋的概念就是让线程执行一个慢循环,可以理解为就是啥也不干,防止从用户态转入内核态。
自适应锁
自适应锁就是自适应的自旋锁,自旋的时间不是固定时间,而是由前一次在同一个锁上的自旋时间和锁的持有者状态来决定。
锁消除
锁消除指的是JVM检测到一些同步的代码块,完全不存在数据竞争的场景,也就是不需要加锁,就会进行锁消除。
锁粗化
锁粗化指的是有很多操作都是对同一个对象进行加锁,就会把锁的同步范围扩展到整个操作序列之外。
CAS 无锁机制
CAS(Compare And Swap/Set) 是一种乐观锁的实现方式,从字面意思上来说是比较并交换/赋值。CAS机制当中使用了内存地址V、旧的预期值A、要修改的新值B3 个基本操作数,更新一个变量的时候,只有当旧的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。
偏向锁
当线程访问同步块获取锁时,会在对象头和栈帧中的锁记录里存储偏向锁的线程 ID,之后这个线程再次进入同步块时都不需要CAS来加锁和解锁了,偏向锁会永远偏向第一个获得锁的线程,如果后续没有其他线程获得过这个锁,持有锁的线程就永远不需要进行同步,反之,当有其他线程竞争偏向锁时,持有偏向锁的线程就会释放偏向锁。
轻量级锁
JVM的对象的对象头中包含有一些锁的标志位,代码进入同步块的时候,JVM 将会使用CAS方式来尝试获取锁,如果更新成功则会把对象头中的状态位标记为轻量级锁,如果更新失败,当前线程就尝试自旋来获得锁。
锁升级过程
锁升级的过程是非常复杂的,好哥哥们自己总结一下语言,尽量简单一点。如下图
14. 有用过 ThreadLocal 吗,原理有了解过吗?
这种问题真想回一个没用过,不会(然后大结局)
首先ThreadLocal是一个存储泛型变量数据类,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。实际上是一种数据隔离(牺牲内存空间)的方式来达到线程安全的目的。
原理
这个的话比较简单,实际上ThreadLocal内部维护了一个Map变量(ThreadLocalMap,并不是HashMap),当调用set 方法时,会将当前线程作为key(实际上这里并不那么准确,应该是将ThreadLocal对象本身作为key,ThreadLocal对象中包含了当前线程),参数作为value,然后设值给ThreadLocal 的静态内部类Map(ThreadLocalMap)中。取值的话就是讲当前线程作为key然后从ThreadLocalMap获取。
本期就到这啦,有不对的地方欢迎好哥哥们评论区留言,另外求关注、求点赞
相关推荐
- VLOOKUP的18种高阶用法大公开!99%的人都不知道的神操作!
-
作为被头条用户催更的Excel课代表,今天带来让HR追着要模板、让老板主动加薪的VLOOKUP终极指南!从基础到高阶一网打尽,文末送36个行业专用模板!一、为什么你的VLOOKUP总报错?血泪大数据...
- Vlooup公式,2种模糊查找匹配,1分钟学会
-
工作中,VLOOKUP公式使用频率是很高的,用来各种查找匹配问题今天我们分享两种模糊查找匹配问题,一种是文本的模糊查找匹配,一种是数字的模糊查找匹配问题1、文本模糊查找匹配使用模拟数据举个例子,原始数...
- 与vlookup功能相似的函数,照样搞定表格数据查询,简单还实用
-
在日常表格数据处理工作,说到数据查询,很多小伙伴首先想到的是Vlookup函数,老师的教程中也多次讲到Vlookup函数的用法和实例。其实在Excel中还有其他的数据查询函数公式或技巧,今天我们先来学...
- 别再折腾VLOOKUP了!DGET逆向查找10秒通关,小白必看
-
今天要掀翻一个“过气网红”——VLOOKUP!你是不是也经历过这些崩溃瞬间:逆向查找要交换列顺序,复制粘贴到手软!多条件查找要嵌套MATCH,公式长到怀疑人生!别忍了!今天教你用DGET函数一键封...
- 职场新人必学!VLOOKUP函数10分钟速成指南
-
正文:"今天来讲解办公人入职期初函数VLOOKUP,这是所有职场人最重要也是最基础的技能。掌握它,90%的数据查找再不用求人!特别献给刚入职场的你——别让Excel成为加班理由。"——...
- 巧用Vlookup函数揪出“第三者”(vlookup第三个参数是什么)
-
在一张Excel表格的重复记录中,让你快速列出每种不同物品第2次或第n次出现的记录,你会怎么做?Vlookup函数就有这个本事。举例来说,产品或者物流表格中往往会记录有同一货物的多笔数据(如下图的今日...
- 分享12个VLOOKUP超经典用法(vlookup通俗易懂)
-
刚毕业那会,面试的时候经常会被问到会不会用Excel?我就理直气壮地回答:“会啊。”毕竟,简历上可是写着熟练。接着面试官扔出一句“那你会VLOOKUP吗?”我还是会一口咬定:“我会。“其实,我都没用过...
- 查找匹配别只知道Vlookup,Sumifs也可以!
-
工作中遇到查找匹配问题的时候,大家第一反应是不是都想到的Vlookup公式呢,有没有小伙伴们给Sumifs一点点机会的呢,有时候Sumifs比Vlookup更好用1、Vlookup公式举个例子,左边是...
- Excel函数讲解:VLOOKUP函数,轻松玩转数据查找
-
常用函数系列教学:VLOOKUP函数讲解(46)。不懂VLOOKUP函数怎么高效查找数据?闲话少叙直接开讲。基本含义:VLOOKUP函数用于在表格按垂直方向(到)上查找返回行数据。如何使用及注意事项?...
- CHOOSEROWS+CHOOSECOLS原来是一个超级查找函数组合!
-
场景一:要在学生名册中,抽查一名学生成绩。公式:=CHOOSEROWS(A1:D5,2)解析:第一参数A1:D5为数据区域,第二参数2表示提取第2行数据。把数据区域改为A2:D5,结合RANDBETW...
- 数据查询不止有vlookup函数,自定义zlookup函数查询操作更高效
-
Excel数据查询,相信大家首先会想到vlookup函数。毋庸置疑vlookup函数在Excel数据查询中作用是非常的强大。但是它也有一些不能实现的数据查询。如上图所示,我们需要根据人员的出现次数,提...
- 「EXCEL进阶」VLOOKUP函数怎么查询一个值返回多个结果
-
前言:VLOOKUP函数一般一次只能返回一个结果,本例介绍通过辅助列的方法使VLOOKUP函数查询一个值,返回这个值对应的多个结果。使用场景举例:根据表格中同一数值,返回对应值的多个结果。比如这张数据...
- WPS查找能手VLOOKUP函数使用方法讲解
-
各位同学好!今天我们来深度剖析WPS最实用的查找工具——VLOOKUP函数。这个函数能帮你在表格中快速定位并提取所需数据,可以帮你快速核对两批数据差异,还可以合并多个表格的关联信息,甚至可以帮你制作动...
- Excel常用10个函数:跨表查找Vlookup,适用于大数据中查找精确值
-
Hello大家好,我是Office米,今天,我们将和大家一起分享交流,常用的10个函数之一:查找引用函数VLOOKUP。在说VLOOKUP函数之前,我们要先了解,平时Excel日常工作中会遇到哪些问题...
- 掌握了这个套路,无论用 Excel vlookup 函数查找第几次结果都很轻松
-
用vlookup查找默认情况下是一对一出结果,如果要一对多查找,就需要用到各种技巧,具体方法我写过非常多了,可以搜索一下历史记录。只要掌握了今天这个套路,无论你想查找第几次重复值,都易如反掌。案例...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- VLOOKUP的18种高阶用法大公开!99%的人都不知道的神操作!
- Vlooup公式,2种模糊查找匹配,1分钟学会
- 与vlookup功能相似的函数,照样搞定表格数据查询,简单还实用
- 别再折腾VLOOKUP了!DGET逆向查找10秒通关,小白必看
- 职场新人必学!VLOOKUP函数10分钟速成指南
- 巧用Vlookup函数揪出“第三者”(vlookup第三个参数是什么)
- 分享12个VLOOKUP超经典用法(vlookup通俗易懂)
- 查找匹配别只知道Vlookup,Sumifs也可以!
- Excel函数讲解:VLOOKUP函数,轻松玩转数据查找
- CHOOSEROWS+CHOOSECOLS原来是一个超级查找函数组合!
- 标签列表
-
- 正版织梦模板 (30)
- 单片机c语言入门基础知识 (32)
- 手机编程游戏 (29)
- 优秀企业网站模板 (34)
- python编程入门自学书籍 (34)
- phpcms安装 (30)
- 自学excel免费视频教程全集 (36)
- php加密系统源码 (29)
- vlookup函数查找 (30)
- 电脑怎么下载java (32)
- vba编程实例速成150例 (30)
- 函数subtotal的用法 (31)
- java教程txt (32)
- java软件开发面试题 (30)
- sql数据库备份与还原方法 (33)
- 后台管理系统网站模板 (30)
- html表单属性有哪些 (31)
- 初中数学三角函数公式 (32)
- python爬虫教程 (30)
- 三角函数值对照表0到360度 (33)
- oracle数据库下载教程 (31)
- index函数什么意思 (34)
- indirect函数的详细用法 (31)
- excel函数round用法 (32)
- vlookup一对多查询并提取 (35)