Java最近面试题2024

1.==和equals⽅法之前的区别?

==:对⽐的是栈中的值,基本数据类型是变量值,引⽤类型是堆中内存对象的地址
equals:object中默认也是采⽤==⽐较,通常会重写

2.hashCode()与equals()之间的关系?

HashCode介绍:hashCode() 的作⽤是获取哈希码,也称为散列码;它实际上是返回⼀个int整数。这
个哈希码的作⽤是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,Java
中的任何类都包含有hashCode() 函数。
散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利⽤
到了散列码!(可以快速找到所需要的对象)

 

3.以“HashSet如何检查重复”为例⼦来说明为什么要有hashCode?

对象加⼊HashSet时,HashSet会先计算对象的hashcode值来判断对象加⼊的位置,看该位置是否有值,如果没有、HashSet会假设对象没有重复出现。但是如果发现有值,这时会调⽤equals()⽅法来检查两个对象是否真的相同。如果两者相同,HashSet就不会让其加⼊操作成功。如果不同的话,就会重新散列到其他位置。这样就⼤⼤减少了equals的次数,相应就⼤⼤提⾼了执⾏速度。
● 如果两个对象相等,则hashcode⼀定也是相同的
● 两个对象相等,对两个对象分别调⽤equals⽅法都返回true
● 两个对象有相同的hashcode值,它们也不⼀定是相等的
● 因此,equals⽅法被覆盖过,则hashCode⽅法也必须被覆盖
● hashCode()的默认⾏为是对堆上的对象产⽣独特值。如果没有重写hashCode(),则该class的两个对象⽆论如何都不会相等(即使这两个对象指向相同的数据)

 

4.final关键字的作⽤是什么?

修饰类:表示类不可被继承
修饰⽅法:表示⽅法不可被⼦类覆盖,但是可以重载
修饰变量:表示变量⼀旦被赋值就不可以更改它的值。
修饰成员变量:
● 如果final修饰的是类变量,只能在静态初始化块中指定初始值或者声明该类变量时指定初始值。
● 如果final修饰的是成员变量,可以在⾮静态初始化块、声明该变量或者构造器中执⾏初始值。
修饰局部变量:系统不会为局部变量进⾏初始化,局部变量必须由程序员显示初始化。因此使⽤final修饰局部变量时,即可以在定义时指定默认值(后⾯的代码不能对变量再赋值),也可以不指定默认值,⽽在后⾯的代码中对final变量赋初值(仅⼀次)

修饰基本类型数据和引⽤类型数据:
如果是基本数据类型的变量,则其数值⼀旦在初始化之后便不能更改;如果是引⽤类型的变量,则在对其初始化之后便不能再让其指向另⼀个对象。但是引⽤的值是可变的。

 

5.String、StringBuffer、StringBuilder的区别?

1.String是不可变的,如果尝试去修改,会新⽣成⼀个字符串对象,StringBuffer和StringBuilder是可
变的
2. StringBuffer是线程安全的,StringBuilder是线程不安全的,所以在单线程环境下StringBuilder效
率会更⾼

6.重载和重写的区别?

1. 重载: 发⽣在同⼀个类中,⽅法名必须相同,参数类型不同、个数不同、顺序不同,⽅法返回值和访问修饰符可以不同,发⽣在编译时。
2. 重写: 发⽣在⽗⼦类中,⽅法名、参数列表必须相同,返回值范围⼩于等于⽗类,抛出的异常范围⼩于等于⽗类,访问修饰符范围⼤于等于⽗类;如果⽗类⽅法访问修饰符为private则⼦类就不能重写该⽅法。

7.List和Set的区别?

List:有序,按对象进⼊的顺序保存对象,可重复,允许多个Null元素对象,可以使⽤Iterator取出所有元素,在逐⼀遍历,还可以使⽤get(int index)获取指定下标的元素
Set:⽆序,不可重复,最多允许有⼀个Null元素对象,取元素时只能⽤Iterator接⼝取得所有元
素,在逐⼀遍历各个元素

 

8.ArrayList和LinkedList区别?

1. ⾸先,他们的底层数据结构不同,ArrayList底层是基于数组实现的,LinkedList底层是基于链表实
现的
2. 由于底层数据结构不同,他们所适⽤的场景也不同,ArrayList更适合随机查找,LinkedList更适合删除和添加,查询、添加、删除的时间复杂度不同

3.另外ArrayList和LinkedList都实现了List接⼝,但是LinkedList还额外实现了Deque接⼝,所以
LinkedList还可以当做队列来使⽤

 

9.谈谈ConcurrentHashMap的扩容机制?

1.7版本
1. 1.7版本的ConcurrentHashMap是基于Segment分段实现的
2. 每个Segment相对于⼀个⼩型的HashMap
3. 每个Segment内部会进⾏扩容,和HashMap的扩容逻辑类似
4. 先⽣成新的数组,然后转移元素到新数组中
5. 扩容的判断也是每个Segment内部单独判断的,判断是否超过阈值
1.8版本
1. 1.8版本的ConcurrentHashMap不再基于Segment实现
2. 当某个线程进⾏put时,如果发现ConcurrentHashMap正在进⾏扩容那么该线程⼀起进⾏扩容
3. 如果某个线程put时,发现没有正在进⾏扩容,则将key-value添加到ConcurrentHashMap中,然
后判断是否超过阈值,超过了则进⾏扩容
4. ConcurrentHashMap是⽀持多个线程同时扩容的
5. 扩容之前也先⽣成⼀个新的数组
6. 在转移元素时,先将原数组分组,将每组分给不同的线程来进⾏元素的转移,每个线程负责⼀组或多组的元素转移⼯作

 

10.Jdk1.7到Jdk1.8 HashMap 发⽣了什么变化(底层)?

1. 1.7中底层是数组+链表,1.8中底层是数组+链表+红⿊树,加红⿊树的⽬的是提⾼HashMap插⼊和
查询整体效率
2. 1.7中链表插⼊使⽤的是头插法,1.8中链表插⼊使⽤的是尾插法,因为1.8中插⼊key和value时需要判断链表元素个数,所以需要遍历链表统计链表元素个数,所以正好就直接使⽤尾插法
3. 1.7中哈希算法⽐较复杂,存在各种右移与异或运算,1.8中进⾏了简化,因为复杂的哈希算法的⽬的就是提⾼散列性,来提供HashMap的整体效率,⽽1.8中新增了红⿊树,所以可以适当的简化哈希算法,节省CPU资源


以上的面试题都是我从微信小程序“卷王搭子”里面获取的,里面不仅有海量的面试题还可以在线做题。有需要的小伙伴可以扫码下方二维码获取:

 

 35b5308eb3c34826acf809cced47b687.png


下面是我创建微信群,有兴趣的小伙伴可以加入,我们一起学习探讨: 

c159fc5fe7d34fb8b9ba3529a3a1bc79.png

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值