进大厂必备的 Java 八股文大全(2022 最强精简易懂版)

很多同学会问 Java 面试八股文有必要背吗?

答案是,必须背,博主是个三本,今年凭借这篇八股文斩获了多个大厂暑期实习 offer,相信秋招一定也可以发挥重要作用。

你可以讨厌这种模式,但你一定要去背,因为不背你就进不了大厂,八股文能快速检验出求职者是否为科班出身,专业基础强不强。国内的互联网面试,恐怕是现存的、最接近科举考试的制度。我整理了一份 Java 基础篇的八股文,大家在面试前可以背一遍,一定能“吊打”面试官。另外,可以关注博主,博主主页有许多归类好的算法题目!

一、Java 基础篇

1.接口和抽象类的区别

(1)抽象类可以有构造方法,而接口没有

(2)抽象类可以有抽象方法和具体方法,接口只能有抽象方法

(3)抽象类的成员 4 种权限修饰符都可以修饰,接口只能用 private

2.重载和重写的区别

重载发生在同一个类中,方法名相同、参数列表、返回类型、权限修饰符可以不同

重写发生在子类中,方法名相、参数列表、返回类型都相同,权限修饰符要大于父类方法,声明异常范围要小于父类方法,但是 final 和 private 修饰的方法不可重写

3.==和 equals 的区别

==比较基本类型,比较的是值,==比较引用类型,比较的是内存地址

equlas 是 Object 类的方法,本质上与==一样,但是有些类重写了 equals 方法,比如 String 的 equals 被重写后,比较的是内存地址,另外重写了 equlas 后,也必须重写 hashcode()方法

4.异常处理机制

(1)使用 try、catch、finaly 捕获异常,finaly 中的代码一定会执行,捕获异常后程序会继续执行

(2)使用 throws 声明该方法可能会抛出的异常类型,出现异常后,程序终止

5.HashMap 原理

1.HashMap 在 Jdk1.8 以后是基于数组+链表+红黑树来实现的,特点是,key 不能重复,可以为 null,线程不安全

2.HashMap 的扩容机制:

HashMap 的默认容量为 16,默认的负载因子为 0.75,当 HashMap 中元素个数超过容量乘以负载因子的个数时,就创建一个大小为前一次两倍的新数组,再将原来数组中的数据复制到新数组中。当数组长度到达 64 且链表长度大于 8 时,链表转为红黑树

3.HashMap 存取原理:

(1)计算 key 的 hash 值,然后进行二次 hash,根据二次 hash 结果找到对应的索引位置

(2)如果这个位置有值,先进性 equals 比较,若结果为 true 则取代该元素,若结果为 false,就使用高低位平移法将节点插入链表(JDK8 以前使用头插法,但是头插法在并发扩容时可能会造成环形链表或数据丢失,而高低位平移发会发生数据覆盖的情况)

6.想要线程安全的 HashMap 怎么办?

(1)使用 ConcurrentHashMap

(2)使用 HashTable

(3)Collections.synchronizedHashMap()方法

7.ConcurrentHashMap 原如何保证的线程安全?

JDK1.7:使用分段锁,将一个 Map 分为了 16 个段,每个段都是一个小的 hashmap,每次操作只对其中一个段加锁

JDK1.8:采用 CAS+Synchronized 保证线程安全,每次插入数据时判断在当前数组下标是否是第一次插入,是就通过 CAS 方式插入,然后判断 f.hash 是否=-1,是的话就说明其他线程正在进行扩容,当前线程也会参与扩容;删除方法用了 synchronized 修饰,保证并发下移除元素安全

8.HashTable 与 HashMap 的区别

(1)HashTable 的每个方法都用 synchronized 修饰,因此是线程安全的,但同时读写效率很低

(2)HashTable 的 Key 不允许为 null

(3)HashTable 只对 key 进行一次 hash,HashMap 进行了两次 Hash

(4)HashTable 底层使用的数组加链表

9.ArrayList 和 LinkedList 的区别

ArratList 的底层使用动态数组,默认容量为 10,当元素数量到达容量时,生成一个新的数组,大小为前一次的 1.5 倍,然后将原来的数组 copy 过来;

因为数组有索引,所以 ArrayList 查找数据更快,但是添加数据效率更低

LinkedList 的底层使用链表,在内存中是离散的,没有扩容机制;LinkedList 在查找数据时需要从头遍历,所以查找慢,但是添加数据效率更高

10.如何保证 ArrayList 的线程安全?

(1)使用 collentions.synchronizedList()方法为 ArrayList 加锁

(2)使用 Vector,Vector 底层与 Arraylist 相同,但是每个方法都由 synchronized 修饰,速度很慢

(3)使用 juc 下的 CopyOnWriterArrayList,该类实现了读操作不加锁,写操作时为 list 创建一个副本,期间其它线程读取的都是原本 list,写操作都在副本中进行,写入完成后,再将指针指向副本。

11.String、StringBuffer、StringBuilder 的区别

String 由 char[] 数组构成,使用了 final 修饰,对 String 进行改变时每次都会新生成一个 String 对象,然后把指针指向新的引用对象。

StringBuffer 可变并且线程安全;

StringBuiler 不可变并且线程不安全。

操作少量字符数据用 String;单线程操作大量数据用 StringBuilder;多线程操作大量数据用 StringBuffer。

二.Java 多线程篇

1.进程和线程的区别

进程:系统运行的基本单位,包含多个线程

线程:独立运行的最小单位,是进程的实体,多个线程共享同一进程内的系统资源

2. 什么是线程上下文切换

当一个线程被剥夺 cpu 使用权时,切换到另外一个线程执行

3.什么是死锁

死锁指多个线程在执行过程中,因争夺资源造成的一种相互等待的僵局

4.死锁的必要条件

互斥条件:同一资源同时只能由一个线程读取

不可抢占条件:不能强行剥夺线程占有的资源

请求和保持条件:请求其他资源的同时对自己手中的资源保持不放

循环等待条件:在相互等待资源的过程中,形成一个闭环

想要预防死锁,只需要破坏其中一个条件即可,银行家算法可以预防死锁

5.Synchrpnized 和 lock 的区别

(1)synchronized 是关键字,lock 是一个类

(2) synchronized 在发生异常时会自动释放锁,lock 需要手动释放锁

(3)synchronized 是可重入锁、非公平锁、不可中断锁,lock 是可重入锁,可中断锁,可以是公平锁

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

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

(2)wait()会释放锁,sleep()不会释放锁

(3)wait()要在同步方法或者同步代码块中执行,sleep()没有限制

(4)wait()要调用 notify()或 notifyall()唤醒,sleep()自动唤醒

7.yield()和 join()区别

yield()调用后线程进入就绪状态

A 线程中调用 B 线程的 join() ,则 B 执行完前 A 进入阻塞状态

8.线程池七大参数

核心线程数:线程池中的基本线程数量

最大线程数:当阻塞队列满了之后,逐一启动

最大线程的存活时间:当阻塞队列的任务执行完后,最大线长的回收时间

最大线程的存活时间单位

阻塞队列:当核心线程满后,后面来的任务都进入阻塞队列

线程工厂:用于生产线程

任务拒绝策略:阻塞队列满后,拒绝任务,有四种策略(1)抛异常(2)丢弃任务不

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值