问遍了身边的面试官朋友,我整理出这份 Java 集合高频面试题(2024年最新版)

最后

看完美团、字节、腾讯这三家的面试问题,是不是感觉问的特别多,可能咱们又得开启面试造火箭、工作拧螺丝的模式去准备下一次的面试了。

开篇有提及我可是足足背下了1000道题目,多少还是有点用的呢,我看了下,上面这些问题大部分都能从我背的题里找到的,所以今天给大家分享一下互联网工程师必备的面试1000题

注意不论是我说的互联网面试1000题,还是后面提及的算法与数据结构、设计模式以及更多的Java学习笔记等,皆可分享给各位朋友

最新“美团+字节+腾讯”一二三面问题,挑战一下你能走到哪一面?

互联网工程师必备的面试1000题

而且从上面三家来看,算法与数据结构是必备不可少的呀,因此我建议大家可以去刷刷这本左程云大佬著作的《程序员代码面试指南 IT名企算法与数据结构题目最优解》,里面近200道真实出现过的经典代码面试题

最新“美团+字节+腾讯”一二三面问题,挑战一下你能走到哪一面?

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

因为 2 个节点在老表是同一个索引位置,因此计算新表的索引位置时,只取决于新表在高位多出来的这一位(图中标红),而这一位的值刚好等于 oldCap。

因为只取决于这一位,所以只会存在两种情况:1)  (e.hash & oldCap) == 0 ,则新表索引位置为“原索引位置” ;2)(e.hash & oldCap) != 0,则新表索引位置为“原索引 + oldCap 位置”。

16、HashMap 是线程安全的吗?

不是。HashMap 在并发下存在数据覆盖、遍历的同时进行修改会抛出 ConcurrentModificationException 异常等问题,JDK 1.8 之前还存在死循环问题。

17、介绍一下死循环问题?

导致死循环的根本原因是 JDK 1.7 扩容采用的是“头插法”,会导致同一索引位置的节点在扩容后顺序反掉,在并发插入触发扩容时形成环,从而产生死循环。

而 JDK 1.8 之后采用的是“尾插法”,扩容后节点顺序不会反掉,不存在死循环问题。

JDK 1.7.0 的扩容代码如下,用例子来看会好理解点。

void transfer(Entry[] newTable) {

Entry[] src = table;

int newCapacity = newTable.length;

for (int j = 0; j < src.length; j++) {

Entry<K,V> e = src[j];

if (e != null) {

src[j] = null;

do {

Entry<K,V> next = e.next;

int i = indexFor(e.hash, newCapacity);

e.next = newTable[i];

newTable[i] = e;

e = next;

} while (e != null);

}

}

}

PS:这个流程较难理解,建议对着代码自己模拟走一遍。

例子:我们有1个容量为2的 HashMap,loadFactor=0.75,此时线程1和线程2 同时往该 HashMap 插入一个数据,都触发了扩容流程,接着有以下流程。

1)在2个线程都插入节点,触发扩容流程之前,此时的结构如下图。

2)线程1进行扩容,执行到代码:Entry<K,V> next = e.next 后被调度挂起,此时的结构如下图。

3)线程1被挂起后,线程2进入扩容流程,并走完整个扩容流程,此时的结构如下图。

由于两个线程操作的是同一个 table,所以该图又可以画成如下图。

4)线程1恢复后,继续走完第一次的循环流程,此时的结构如下图。

5)线程1继续走完第二次循环,此时的结构如下图。

6)线程1继续执行第三次循环,执行到 e.next = newTable[i] 时形成环,执行完第三次循环的结构如下图。

如果此时线程1调用 map.get(11) ,悲剧就出现了——无限循环。

18、总结下 JDK 1.8 主要进行了哪些优化?

JDK 1.8 的主要优化刚才我们都聊过了,主要有以下几点:

1)底层数据结构从“数组+链表”改成“数组+链表+红黑树”,主要是优化了 hash 冲突较严重时,链表过长的查找性能:O(n) -> O(logn)。

2)计算 table 初始容量的方式发生了改变,老的方式是从1开始不断向左进行移位运算,直到找到大于等于入参容量的值;新的方式则是通过“5个移位+或等于运算”来计算。

// JDK 1.7.0

public HashMap(int initialCapacity, float loadFactor) {

// 省略

// Find a power of 2 >= initialCapacity

int capacity = 1;

while (capacity < initialCapacity)

capacity <<= 1;

// … 省略

}

// JDK 1.8.0_191

static final int tableSizeFor(int cap) {

int n = cap - 1;

n |= n >>> 1;

n |= n >>> 2;

n |= n >>> 4;

n |= n >>> 8;

n |= n >>> 16;

return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;

}

3)优化了 hash 值的计算方式,老的通过一顿瞎JB操作,新的只是简单的让高16位参与了运算。

4)扩容时插入方式从“头插法”改成“尾插法”,避免了并发下的死循环。

5)扩容时计算节点在新表的索引位置方式从“h & (length-1)”改成“hash & oldCap”,性能可能提升不大,但设计更巧妙、更优雅。

19、Hashtable 是怎么加锁的 ?

Hashtable 通过 synchronized 修饰方法来加锁,从而实现线程安全。

public synchronized V get(Object key) {

// …

}

public synchronized V put(K key, V value) {

// …

}

20、LinkedHashMap 和 TreeMap 排序的区别?

LinkedHashMap 和 TreeMap 都是提供了排序支持的 Map,区别在于支持的排序方式不同:

LinkedHashMap:保存了数据的插入顺序,也可以通过参数设置,保存数据的访问顺序。

TreeMap:底层是红黑树实现。可以指定比较器(Comparator 比较器),通过重写 compare 方法来自定义排序;如果没有指定比较器,TreeMap 默认是按 Key 的升序排序(如果 key 没有实现 Comparable接口,则会抛异常)。

21、HashMap 和 Hashtable 的区别?

HashMap 允许 key 和 value 为 null,Hashtable 不允许。

HashMap 的默认初始容量为 16,Hashtable 为 11。

HashMap 的扩容为原来的 2 倍,Hashtable 的扩容为原来的 2 倍加 1。

HashMap 是非线程安全的,Hashtable 是线程安全的,使用 synchronized 修饰方法实现线程安全。

HashMap 的 hash 值重新计算过,Hashtable 直接使用 hashCode。

HashMap 去掉了 Hashtable 中的 contains 方法。

HashMap 继承自 AbstractMap 类,Hashtable 继承自 Dictionary 类。

HashMap 的性能比 Hashtable 高,因为 Hashtable 使用 synchronized 实现线程安全,还有就是 HashMap 1.8 之后底层数据结构优化成 “数组+链表+红黑树”,在极端情况下也能提升性能。

22、介绍下 ConcurrenHashMap,要讲出 1.7 和 1.8 的区别?

ConcurrentHashMap 是 HashMap 的线程安全版本,和 HashMap 一样,在JDK 1.8 中进行了较大的优化。

JDK1.7:底层结构为:分段的数组+链表;实现线程安全的方式:分段锁(Segment,继承了ReentrantLock),如下图所示。

JDK1.8:底层结构为:数组+链表+红黑树;实现线程安全的方式:CAS + Synchronized

区别:

1、JDK1.8 中降低锁的粒度。JDK1.7 版本锁的粒度是基于 Segment 的,包含多个节点(HashEntry),而 JDK1.8 锁的粒度就是单节点(Node)。

2、JDK1.8 版本的数据结构变得更加简单,使得操作也更加清晰流畅,因为已经使用 synchronized 来进行同步,所以不需要分段锁的概念,也就不需要 Segment 这种数据结构了,当前还保留仅为了兼容。

3、JDK1.8 使用红黑树来优化链表,跟 HashMap 一样,优化了极端情况下,链表过长带来的性能问题。

4、JDK1.8 使用内置锁 synchronized 来代替重入锁 ReentrantLock,synchronized 是官方一直在不断优化的,现在性能已经比较可观,也是官方推荐使用的加锁方式。

23、ConcurrentHashMap 的并发扩容

ConcurrentHashMap 在扩容时会计算出一个步长(stride),最小值是16,然后给当前扩容线程分配“一个步长”的节点数,例如16个,让该线程去对这16个节点进行扩容操作(将节点从老表移动到新表)。

如果在扩容结束前又来一个线程,则也会给该线程分配一个步长的节点数让该线程去扩容。依次类推,以达到多线程并发扩容的效果。

例如:64要扩容到128,步长为16,则第一个线程会负责第113(索引112)128(索引127)的节点,第二个线程会负责第97(索引96)112(索引111)的节点,依次类推。

具体处理(该流程后续可能会替换成流程图):

1)如果索引位置上为null,则直接使用 CAS 将索引位置赋值为 ForwardingNode(hash值为-1),表示已经处理过,这个也是触发并发扩容的关键点。

2)如果索引位置的节点 f 的 hash 值为 MOVED(-1),则代表节点 f 是 ForwardingNode 节点,只有 ForwardingNode 的 hash 值为 -1,意味着该节点已经处理过了,则跳过该节点继续往下处理。

3).否则,对索引位置的节点 f 对象使用 synchronized 进行加锁,遍历链表或红黑树,如果找到 key 和入参相同的,则替换掉 value 值;如果没找到,则新增一个节点。如果是链表,同时判断是否需要转红黑树。处理完在索引位置的节点后,会将该索引位置赋值为 ForwardingNode,表示该位置已经处理过。

ForwardingNode:一个特殊的 Node 节点,hash 值为-1(源码中定义成 MOVED),其中存储 nextTable 的引用。 只有发生扩容的时候,ForwardingNode才会发挥作用,作为一个占位符放在 table 中表示当前节点已经被处理(或则为 null )。

24、ConcurrenHashMap 和 Hashtable 的区别?

1)底层数据结构:

ConcurrentHashMap:1)JDK1.7 采用 分段的数组+链表 实现;2)JDK1.8 采用 数组+链表+红黑树,跟 JDK1.8 的 HashMap 的底层数据结构一样。

Hashtable: 采用 数组+链表 的形式,跟 JDK1.8 之前的 HashMap 的底层数据结构类似。

2)实现线程安全的方式(重要):

ConcurrentHashMap:

1)JDK1.7:使用分段锁(Segment)保证线程安全,每个分段(Segment)包含若干个 HashEntry,当并发访问不同分段的数据时,不会产生锁竞争,从而提升并发性能。

2)JDK1.8:使用 synchronized + CAS 的方式保证线程安全,每次只锁一个节点(Node),进一步降低锁粒度,降低锁冲突的概率,从而提升并发性能。

Hashtable:使用 synchronized 修饰方法来保证线程安全,每个实例对象只有一把锁,并发性能较低,相当于串行访问。

25、ConcurrentHashMap 的 size() 方法怎么实现的?

JDK 1.7:先尝试在不加锁的情况下尝进行统计 size,最多统计3次,如果连续两次统计之间没有任何对 segment 的修改操作,则返回统计结果。否则,对每个segment 进行加锁,然后统计出结果,返回结果。

JDK 1.8:直接统计 baseCount 和 counterCells 的 value 值,返回的是一个近似值,如果有并发的插入或删除,实际的数量可能会有所不同。

该统计方式改编自 LongAdder 和 Striped64,这两个类在 JDK 1.8 中被引入,出自并发大神 Doug Lea 之手,是原子类(AtomicLong 等)的优化版本,主要优化了在并发竞争下,AtomicLong 由于 CAS 失败的带来的性能损耗。

值得注意的是,JDK1.8中,提供了另一个统计的方法 mappingCount,实现和 size 一样,只是返回的类型改成了 long,这也是官方推荐的方式。

public int size() {

long n = sumCount();

return ((n < 0L) ? 0 :

(n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :

(int)n);

}

// 一个ConcurrentHashMap包含的映射数量可能超过int上限,

// 所以应该使用这个方法来代替size()

public long mappingCount() {

long n = sumCount();

return (n < 0L) ? 0L : n; // ignore transient negative values

}

final long sumCount() {

CounterCell[] as = counterCells; CounterCell a;

long sum = baseCount;

if (as != null) {

for (int i = 0; i < as.length; ++i) {

if ((a = as[i]) != null)

sum += a.value;

}

}

return sum;

}

26、比较下常见的几种 Map,在使用时怎么选择?

30、ArrayList 和 Vector 的区别。

Vector 和 ArrayList 的实现几乎是一样的,区别在于:

1)最重要的的区别: Vector 在方法上使用了 synchronized 来保证线程安全,同时由于这个原因,在性能上 ArrayList 会有更好的表现。

2) Vector 扩容后容量默认变为原来 2 倍,而 ArrayList 为原来的 1.5 倍。

有类似关系的还有:StringBuilder 和 StringBuffer、HashMap 和 Hashtable。

31、ArrayList 和 LinkedList 的区别?

1、ArrayList 底层基于动态数组实现,LinkedList 底层基于双向链表实现。

2、对于随机访问(按 index 访问,get/set方法):ArrayList 通过 index 直接定位到数组对应位置的节点,而 LinkedList需要从头结点或尾节点开始遍历,直到寻找到目标节点,因此在效率上 ArrayList 优于 LinkedList。

3、对于随机插入和删除:ArrayList 需要移动目标节点后面的节点(使用System.arraycopy 方法移动节点),而 LinkedList 只需修改目标节点前后节点的 next 或 prev 属性即可,因此在效率上 LinkedList 优于 ArrayList。

4、对于顺序插入和删除:由于 ArrayList 不需要移动节点,因此在效率上比 LinkedList 更好。这也是为什么在实际使用中 ArrayList 更多,因为大部分情况下我们的使用都是顺序插入。

5、两者都不是线程安全的。

6、内存空间占用: ArrayList 的空 间浪费主要体现在在 list 列表的结尾会预留一定的容量空间,而 LinkedList 的空间花费则体现在它的每一个元素都需要消耗比 ArrayList 更多的空间(因为要存放直接后继和直接前驱以及数据)。

32、HashSet 是如何保证不重复的?

HashSet 底层使用 HashMap 来实现,见下面的源码,元素放在 HashMap 的 key 里,value 为固定的 Object 对象。当 add 时调用 HashMap 的 put 方法,如果元素不存在,则返回 null 表示 add 成功,否则 add 失败。

由于 HashMap 的 Key 值本身就不允许重复,HashSet 正好利用 HashMap 中 key 不重复的特性来校验重复元素,简直太妙了。

private transient HashMap<E,Object> map;

// Dummy value to associate with an Object in the backing Map

private static final Object PRESENT = new Object();

public boolean add(E e) {

return map.put(e, PRESENT)==null;

}

33、TreeSet 清楚吗?能详细说下吗?

“TreeSet 和 TreeMap 的关系” 和上面说的 “HashSet 和 HashMap 的关系” 几乎一致。

TreeSet 底层默认使用 TreeMap 来实现。而 TreeMap 通过实现 Comparator(或 Key 实现 Comparable)来实现自定义顺序。

private transient NavigableMap<E,Object> m;

private static final Object PRESENT = new Object();

TreeSet(NavigableMap<E,Object> m) {

this.m = m;

}

public TreeSet() {

this(new TreeMap<E,Object>());

}

public boolean add(E e) {

return m.put(e, PRESENT)==null;

}

34、介绍下 CopyOnWriteArrayList?

CopyOnWriteArrayList 是 ArrayList 的线程安全版本,也是大名鼎鼎的 copy-on-write(COW,写时复制)的一种实现。

在读操作时不加锁,跟ArrayList类似;在写操作时,复制出一个新的数组,在新数组上进行操作,操作完了,将底层数组指针指向新数组。适合使用在读多写少的场景。

例如 add(E e) 方法的操作流程如下:使用 ReentrantLock 加锁,拿到原数组的length,使用 Arrays.copyOf 方法从原数组复制一个新的数组(length+1),将要添加的元素放到新数组的下标length位置,最后将底层数组指针指向新数组。

35、Comparable 和 Comparator 比较?

1、Comparable 是排序接口,一个类实现了 Comparable接口,意味着“该类支持排序”。Comparator 是比较器,我们可以实现该接口,自定义比较算法,创建一个 “该类的比较器” 来进行排序。

2、Comparable 相当于“内部比较器”,而 Comparator 相当于“外部比较器”。

3、Comparable 的耦合性更强,Comparator 的灵活性和扩展性更优。

4、Comparable 可以用作类的默认排序方法,而 Comparator 则用于默认排序不满足时,提供自定义排序。

耦合性和扩展性的问题,举个简单的例子:

当实现类实现了 Comparable 接口,但是已有的 compareTo 方法的比较算法不满足当前需求,此时如果想对两个类进行比较,有两种办法:

1)修改实现类的源代码,修改 compareTo 方法,但是这明显不是一个好方案,因为这个实现类的默认比较算法可能已经在其他地方使用了,此时如果修改可能会造成影响,所以一般不会这么做。

2)实现 Comparator 接口,自定义一个比较器,该方案会更优,自定义的比较器只用于当前逻辑,其他已有的逻辑不受影响。

36、List、Set、Map三者的区别?

List(对付顺序的好帮手): 存储的对象是可重复的、有序的。

Set(注重独一无二的性质):存储的对象是不可重复的、无序的。

Map(用 Key 来搜索的专业户): 存储键值对(key-value),不能包含重复的键(key),每个键只能映射到一个值。

37、Map、List、Set 分别说下你了解到它们有的线程安全类和线程不安全的类?

Map

线程安全:CocurrentHashMap、Hashtable

线程不安全:HashMap、LinkedHashMap、TreeMap、WeakHashMap

List

总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。实际上,作为程序员,丰富自己的知识储备,提升自己的知识深度和广度是很有必要的。

Mybatis源码解析

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

: 存储的对象是可重复的、有序的。

Set(注重独一无二的性质):存储的对象是不可重复的、无序的。

Map(用 Key 来搜索的专业户): 存储键值对(key-value),不能包含重复的键(key),每个键只能映射到一个值。

37、Map、List、Set 分别说下你了解到它们有的线程安全类和线程不安全的类?

Map

线程安全:CocurrentHashMap、Hashtable

线程不安全:HashMap、LinkedHashMap、TreeMap、WeakHashMap

List

总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。实际上,作为程序员,丰富自己的知识储备,提升自己的知识深度和广度是很有必要的。

Mybatis源码解析

[外链图片转存中…(img-Ow1p1oXd-1715711976665)]

[外链图片转存中…(img-El9gDkJf-1715711976665)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 1. Java中的基本数据类型有哪些?它们的大小是多少? 答:Java中的基本数据类型有byte、short、int、long、float、double、char和boolean。它们的大小分别为8位、16位、32位、64位、32位、64位、16位和1位。 2. Java中的访问修饰符有哪些?它们分别代表什么意思? 答:Java中的访问修饰符有public、protected、default和private。它们分别代表公开的、受保护的、默认的和私有的。 3. Java中的final关键字有什么作用? 答:final关键字可以用来修饰类、方法和变量。它的作用是使被修饰的类、方法或变量不可被继承、重写或修改。 4. Java中的static关键字有什么作用? 答:static关键字可以用来修饰类、方法和变量。它的作用是使被修饰的类、方法或变量在内存中只有一份拷贝,可以直接通过类名访问。 5. Java中的抽象类和接口有什么区别? 答:抽象类和接口都是用来实现多态的机制。抽象类可以包含抽象方法和非抽象方法,可以有构造方法和成员变量,不能被实例化。接口只能包含抽象方法和常量,不能有构造方法和成员变量,可以被多个类实现。 6. Java中的重载和重写有什么区别? 答:重载是指在同一个类中定义多个方法,它们的方法名相同但参数列表不同。重写是指子类重写父类的方法,方法名和参数列表都相同。 7. Java中的异常处理机制是什么? 答:Java中的异常处理机制是通过try-catch-finally语句块来实现的。当程序现异常时,会抛一个异常对象,可以通过catch语句捕获并处理异常,finally语句块中的代码会在try或catch语句块执行完毕后执行。 8. Java中的线程是什么?如何创建线程? 答:线程是程序执行的最小单位,可以同时执行多个线程实现并发执行。可以通过继承Thread类或实现Runnable接口来创建线程,然后调用start()方法启动线程。 9. Java中的集合框架有哪些?它们的区别是什么? 答:Java中的集合框架包括List、Set、Map和Queue等。它们的区别在于List是有序的、可重复的集合,Set是无序的、不可重复的集合,Map是键值对的集合,Queue是队列集合。 10. Java中的反射机制是什么?如何使用反射? 答:Java中的反射机制是指在运行时动态获取类的信息和调用类的方法。可以通过Class类的实例来获取类的信息,然后使用反射API来调用类的方法。使用反射可以实现动态加载类、动态创建对象、动态调用方法等功能。 ### 回答2: Java作为一门广泛应用于软件开发的编程语言,被越来越多的公司和企业所采用。因此,Java开发工程师也成为各大公司中的热门职位之一。为了能够通过Java开发工程师的面试,我们需要对Java基础知识进行深入学习。以下是Java基础高频面试题(2021最新版)。 1. Java语言的特性? Java语言有四个特点,分别是: 1.1 简单性:Java语言的设计非常简单,易于使用和学习,减少了语言的复杂度。 1.2 面向对象:Java语言支持面向对象的编程方式,有助于代码的重用性和维护性。 1.3 平台无关性:Java语言可以在不同的平台上运行,具有跨平台的特性。 1.4 安全性:在Java语言中,提供了许多安全机制,如类的访问控制、安全管理器等,能够保证程序的安全性和正确性。 2. Java中包是什么? Java中的包是一种组织程序的方式,它能够将相关的类、接口和其他文件组织在一起,形成一个层次结构。Java中的包有助于代码的重用性和可维护性。 3. Java语言的数据类型有哪些? Java语言支持的数据类型包括: 3.1 基本数据类型:byte、short、int、long、float、double、char、boolean。 3.2 引用数据类型:类、接口、数组。 4. String和StringBuffer有什么区别? String是Java中的一个不可变的字符串类,所有的字符串操作都是创建新的String对象,因此会占用大量的内存。而StringBuffer是可变的字符串类,可以动态修改其中的内容,在进行字符串操作时不会产生新的String对象,因此可以减少内存的消耗。 5. Java中的异常处理机制是什么? Java的异常处理机制可以帮助程序员处理程序发生的异常情况,包括编译时异常和运行时异常。在Java中,异常由try-catch块捕获,通过throw语句抛异常。 6. final、finally、finalize有什么区别? final是Java中的一个关键字,可以修饰类、方法和变量。在修饰类时,表示该类不能被继承;在修饰方法时,表示该方法不能被覆盖;在修饰变量时,表示该变量是一个常量,不能被修改。 finally是Java中的一个关键字,可以用在try-catch块中,表示无论try和catch块中的代码是否发生异常,都会执行finally块中的代码。 finalize是Java中的一个方法,是Object类中的一个方法,用于垃圾回收时执行的方法,用来释放对象占据的资源。 7. Java中系统输入输有哪些方法? Java中的System类提供了3种标准I/O流: 7.1 标准输入流:System.in,用于读取用户在命令行中输入的数据。 7.2 标准输流:System.out,用于将数据输到命令行中。 7.3 标准错误流:System.err,用于输错误信息。 8. Java中的多线程是怎么实现的? Java中的多线程机制通过线程对象和run()方法来实现。在Java中,线程是Thread类的对象,每个线程都有自己的run()方法,用于执行线程的任务。通过调用start()方法来启动线程,等到线程调度器分配时间片之后,线程才开始执行。如果要停止执行线程,可以调用stop()方法,但不建议使用该方法,因为可能会导致一些不可预料的结果发生。 9. Java中的集合框架有哪些? Java中的集合框架包括Collection和Map两个接口,分别用于存储对象的集合和键值对的映射集合。常用的集合类型包括:List、Set、Map、Queue。 10. Java中的泛型是什么? 泛型是Java中的一个特性,可以使得代码更加灵活和类型安全。通过使用泛型,可以将类型作为参数传递到方法或类中,并在程序运行时根据实际传递的类型进行编译。 以上是Java基础高频面试题(2021最新版),希望对广大读者在Java开发工程师的面试中有所帮助。 ### 回答3: Java是一门广泛应用于各行各业的编程语言,它的应用范围包括大型企业级系统、游戏开发、移动应用程序以及物联网等。Java基础面试题面试Java开发人员时必不可少的环节,下面我会简要介绍一些最新的2021Java基础面试题。 1. Java中的四种访问修饰符是什么?他们分别表示什么? 答:Java中的四种访问修饰符包括:public、protected、private和default(没有显示声明访问修饰符,则默认为default)。public表示变量或方法可以在任何地方被调用;protected表示变量或方法限制为同一包内或者其子类中使用;private表示变量或方法只能在当前类中使用;default表示变量或方法在同一包内可见。 2. Java中object类的基本方法有哪些?请解释这些方法的作用。 答:Object类的基本方法包括:equals()、hashCode()、toString()、clone()和finalize()。equals()方法用于判断两个对象是否相等,需要进行重写;hashCode()方法返回一个哈希码值,用于快速查找数据;toString()方法用于返回一个对象的字符串表示形式;clone()方法用于创建一个对象的副本;finalize()方法在垃圾回收之前被调用,用于释放对象占用的资源。 3. 什么是Java中的接口?接口有什么作用? 答:Java中的接口是一个包含方法签名和常量的集合,它可以被类实现。Java中的实现类必须实现接口中定义的所有方法,否则就必须声明自己为抽象类。接口定义了一种规范,使得类可以按照规范进行编写。接口主要用于实现解耦,使开发人员可以更轻松地维护和升级代码。 4. Java中的final关键字有什么作用? 答:final关键字可以用于修饰类、方法和变量。final修饰类表示该类不能被继承;final修饰方法表示该方法不能被子类重写;final修饰变量表示该变量的值不能被修改。final关键字除了保护对象的线程安全和防止错误修改外,还可以提高代码的性能。 5. Java中的static关键字有什么作用? 答:static关键字可以用于修饰类、方法和变量。static修饰类表示该类的变量和方法可以直接通过类名调用,不需要实例化类;static修饰方法表示该方法是属于类的,而不是属于对象的;static修饰变量表示该变量是属于类的,而不是属于对象的。static关键字可以提高程序的性能和代码的复用性。 以上是2021Java基础面试题的简要介绍,当然这些只是一部分,Java基础知识广泛且深刻,希望大家在准备面试时能够多加练习掌握相关知识,从而更好地应对Java面试挑战。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值