Java高频面试题解析,直戳面试官痛点,多家互联网大厂Offer等你拿

欠伸展肢体,吟咏心自愉。这篇文章主要讲述Java高频面试题解析,直戳面试官痛点,多家互联网大厂Offer等你拿相关的知识,希望能为你提供帮助。
前言



回顾多灾多难的2021年,新冠疫情持续肆虐全球,疫情确诊曲线起伏跌宕,由此引发一系列事件:经济萎缩、 财政刺激、疫苗研发、经济复苏等等。无不牵动着市场的神经。“后疫情时代”将重新定义2022年,新旧交接之际,把握机遇。珍惜当下。
关于面试,特整合了java面试题,希望对找工作、跳槽的小伙伴有所帮助。总之一句话越基础的东西越重要,很多人认为自己会用它们写代码了,其实仅仅是知道如何调用api而已,离会用还差的远。互联网发展迅速的时代,只能跟上时代的进步,才不会被淘汰。


Java基础1、List和Set的区别。
2、HashSet是如何保证不重复的?
3、HashMap是线程安全的吗,为什么不是线程安全的(最好画图说明多线程环境下不安全)?
4、HashMap的扩容过程。
5、HashMap1.7与1.8的 区别,说明1.8做了哪些优化,如何优化的?
【Java高频面试题解析,直戳面试官痛点,多家互联网大厂Offer等你拿】6、final finally finalize。
7、强引用 、软引用、 弱引用、虚引用。
8、Java反射。
9、Arrays.sort 实现原理和Collection实现原理。
10、LinkedHashMap的应用。
Java 并发1、synchronized的实现原理以及锁优化?
2、volatile的实现原理?
3、Java的信号灯?
4、synchronized在静态方法和普通方法的区别?
5、怎么实现所有线程在等待某个事件的发生才会去执行?
JVM1.JVM的内存结构。
2.JVM方法栈的工作过程,方法栈和本地方法栈有什么区别?
3.JVM的栈中引用如何和堆中的对象产生关联。
4.可以了解一下逃逸分析技术。
5.GC的常见算法,CMS以及G1的垃圾回收过程,CMS的各个阶段哪两个是Stop the world的,CMS会不会产生碎片,G1的优势。
6.标记清除和标记整理算法的理解以及优缺点。
7.eden survivor区的比例,为什么是这个比例,eden survivor的工作过程。
8.JVM如何判断一个对象是否该被GC,可以视为root的都有哪几种类型?
9.强软弱虚引用的区别以及GC对他们执行怎样的操作?
10.Java是否可以GC直接内存。


这些问题都是抽取了部分发出来,答案解析和知识点都整理在Java文档里了,详细内容有很多,为了不影响阅读,可看整理的《Java架构进阶面试题手册》。


Spring1、BeanFactory和FactoryBean?
2、Spring IOC的理解,其初始化过程?
3、BeanFactory和ApplicationContext?
4、Spring Bean的生命周期,如何被管理的?
5、Spring Bean的加载过程是怎样的?
6、如果要你实现Spring AOP,请问怎么实现?
7、如果要你实现Spring IOC,你会注意哪些问题?
8、Spring是如何管理事务的,事务管理机制?
SpringBoot-Spring Cloud1、什么是Spring Boot?
2、SpringBoot有哪些优点?
3、什么是JavaConfig?
4、4、如何重新加载Spring Boot上的更改,而无需重新启动服务器?
5、Spring Boot中的监视器是什么?
6、如何在Spring Boot中禁用Actuator端点安全性?
7、如何在自定义端口上运行Spring Boot应用程序?
8、什么是YAML?
9、如何实现Spring Boot应用程序的安全性?
10、如何集成Spring Boot和ActiveMQ?
Redis1.RDB和AOF区别。
2.为什么RDB要fork子进程而不是线程。
3.redis基本数据类型。
4.zset的底层数据结构,跳表何时增加高度。
5.分布式redis,缓存和数据库读写不一致,答延迟双删。
mysql高频20题解析1.事务四大特性(ACID)原子性、一致性、隔离性、持久性?
2.事务的并发?事务隔离级别,每个级别会引发什么问题,MySQL默认是哪个级别?
3.MySQL常见的三种存储引擎(InnoDB、MyISAM、MEMORY)的区别?
4.MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别,各自的适用场景?
5.查询语句不同元素(where、jion、limit、group by、having等等)执行先后顺序?
多线程1.Java实现多线程有哪几种方式?
2.Callable和Future的了解。
3.线程池的参数有哪些,在线程池创建一个线程的过程。
4.volitile关键字的作用,原理。
5.synchronized关键字的用法,优缺点。
Netty1.Netty 是什么?
2.Netty 的特点是什么?
3.Netty 的优势有哪些?
4.Netty 的应用场景有哪些?
5.Netty 高性能表现在哪些方面?
ZooKeeper1.ZooKeeper是什么?
2.ZooKeeper提供了什么?
3.Zookeeper文件系统。
4.Zookeeper怎么保证主从节点的状态同步?
5.四种类型的数据节点Znode。
Tomcat1.Tomcat是什么?
2.Tomcat的缺省端口是多少,怎么修改?
3.tomcat有哪几种Connector运行模式(优化)?
4.Tomcat有几种部署方式?
5.tomcat容器是如何创建servlet类实例?用到了什么原理?
解决方案篇
  1. API接口安全设计
  2. 秒杀系统设计思路
  3. 分布式事务解决方案
  4. SSO单点登录方案
  5. Redis缓存和MySQL数据一致性方案详解
  6. 分库分表设计
  7. 缓存雪崩,穿透,击穿解决方案
面向对象什么是面向对象?
对比面向过程,是两种不同的处理问题的角度面向过程更注重事情的每一个步骤及顺序,面向对象更注重事情有哪些参与者(对象)、及各自需要做什么
比如:洗衣机洗衣服面向过程会将任务拆解成一系列的步骤(函数),1、打开洗衣机-----> 2、放衣服-----> 3、放洗衣粉-----> 4、清洗 > 5、烘干面向对象会拆出人和洗衣机两个对象: 人:打开洗衣机 放衣服 放 洗 衣 粉 洗衣机:清洗 烘干从以上例子能看出,面向过程比较直接高效,而面向对象更易于复用、扩展和维护
面向对象
封装:封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项内部细节对外部调用透明,外部调用无需修改或者关心内部实现
1、javabean的属性私有,提供getset对外访问,因为属性的赋值或者获取逻辑只能由javabean本身决 定。而不能由外部胡乱修改该name有自己的命名规则,明显不能由外部直接赋值
private String name;
public void setName(String name) this.name = "tuling_"+name;

2、orm框架
操作数据库,我们不需要关心链接是如何建立的、sql是如何执行的,只需要引入mybatis,调方法即可。
继承:继承基类的方法,并做出自己的改变和/或扩展子类共性的方法或者属性直接使用父类的,而不需要自己再定义,只需扩展自己个性化的。
多态:基于对象所属类的不同,外部对同一个方法的调用,实际执行的逻辑不同。 继承,方法重写,父类引用指向子类对象,父类类型 变量名 = new 子类对象 ; 变量名.方法名(); 无法调用子类特有的功能。
JDK JRE JVMJDK:
Java Develpment Kit java 开发工具
JRE:
Java Runtime Environment java运行时环境JVM:
java Virtual Machine java 虚拟机
==和equals比较==对比的是栈中的值,基本数据类型是变量值,引用类型是堆中内存对象的地址
equals:object中默认也是采用==比较,通常会重写Object
public boolean equals(Object obj)return (this == obj);

String
上述代码可以看出,String类中被复写的equals()方法其实是比较两个字符串的内容。
public boolean equals(Object anObject)if (this == anObject)
return true;

if (anObject instanceof String)
String anotherString = (String)anObject; int n = value.length;
if (n == anotherString.value.length)char v1[] = value;
char v2[] = anotherString.value; int i = 0;
while (n-- != 0)
if (v1i != v2i) return false;
i++;

return true;


return false;

public class StringDemo
public static void main(String args[])String str1 = "Hello";
String str2 = new String("Hello"); String str3 = str2; // 引用传递
System.out.println(str1 == str2); // false System.out.println(str1 == str3); // false System.out.println(str2 == str3); // true System.out.println(str1.equals(str2)); // true System.out.println(str1.equals(str3)); // true System.out.println(str2.equals(str3)); // true


hashCode与equalshashCode介绍:
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,Java中的任何类都包含有hashCode() 函数。
散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用 到了散列码!(可以快速找到所需要的对象)
为什么要有hashCode:
以“HashSet如何检查重复”为例子来说明为什么要有hashCode:对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,看该位置是否有 值,如果没有、HashSet会假设对象没有重复出现。但是如果发现有值,这时会调用equals()方法来 检查两个对象是否真的相同。如果两者相同,HashSet就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。这样就大大减少了equals的次数,相应就大大提高了执行速度。
如果两个对象相等,则hashcode一定也是相同的两个对象相等,对两个对象分别调用equals方法都返回true 两个对象有相同的hashcode值,它们也不一定是相等的因此,equals方法被覆盖过,则hashCode方法也必须被覆盖hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个 对象无论如何都不会相等(即使这两个对象指向相同的数据)
final最终的
修饰类:表示类不可被继承
修饰方法:表示方法不可被子类覆盖,但是可以重载修饰变量:表示变量一旦被赋值就不可以更改它的值。
  1. 修饰成员变量
如果final修饰的是类变量,只能在静态初始化块中指定初始值或者声明该类变量时指定初始值。如果final修饰的是成员变量,可以在非静态初始化块、声明该变量或者构造器中执行初始值。
  1. 修饰局部变量
系统不会为局部变量进行初始化,局部变量必须由程序员显示初始化。因此使用final修饰局部变量时, 即可以在定义时指定默认值(后面的代码不能对变量再赋值),也可以不指定默认值,而在后面的代码 中对final变量赋初值(仅一次)
public class FinalVar
final static int a = 0; //再声明的时候就需要赋值 或者静态代码块赋值
/** static
a = 0;

*/
final int b = 0; //再声明的时候就需要赋值 或者代码块中赋值 或者构造器赋值
/*
b = 0;
*/
public static void main(String[] args)

final int localA; //局部变量只声明没有初始化,不会报错,与final无关。localA = 0; //在使用之前一定要赋值
//localA = 1; 但是不允许第二次赋值


  1. 修饰基本类型数据和引用类型数据
如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。但是引用的值是可变 的。
public class FinalReferenceTest public static void main()
final int[] iArr=1,2,3,4; iArr2=-3; //合法
iArr=null; //非法,对iArr不能重新赋值
final Person p = new Person(25);
p.setAge(24); //合法
p=null; //非法


为什么局部内部类和匿名内部类只能访问局部final变量?编译之后会生成两个class文件,Test.class Test1.class
public class Test
public static void main(String[] args)

//局部final变量a,b

public void test(final int b) //jdk8在这里做了优化, 不用写,语法糖,但实际上也是有的,也不能修改
final int a = 10;
//匿名内部类new Thread()
public void run()System.out.println(a); System.out.println(b);
;
.start();


class OutClass
private int age = 12;
public void outPrint(final int x)class InClass
public void InPrint()
System.out.println(x); System.out.println(age);


new InClass().InPrint();


首先需要知道的一点是: 内部类和外部类是处于同一个级别的,内部类不会因为定义在方法中就会随着方法的执行完毕就被销毁。
这里就会产生问题:当外部类的方法结束时,局部变量就会被销毁了,但是内部类对象可能还存在(只有 没有人再引用它时,才会死亡)。这里就出现了一个矛盾:内部类对象访问了一个不存在的变量。为了解 决这个问题,就将局部变量复制了一份作为内部类的成员变量,这样当局部变量死亡后,内部类仍可以 访问它,实际访问的是局部变量的"copy"。这样就好像延长了局部变量的生命周期将局部变量复制为内部类的成员变量时,必须保证这两个变量是一样的,也就是如果我们在内部类中修 改了成员变量,方法中的局部变量也得跟着改变,怎么解决问题呢?
就将局部变量设置为final,对它初始化后,我就不让你再去修改这个变量,就保证了内部类的成员变量和方法的局部变量的一致性。这实际上也是一种妥协。使得局部变量与内部类内建立的拷贝保持一致。
String、StringBuffer、StringBuilderString是final修饰的,不可变,每次操作都会产生新的String对象StringBuffer和StringBuilder都是在原对象上操作StringBuffer是线程安全的,StringBuilder线程不安全的StringBuffer方法都是synchronized修饰的性能:StringBuilder > StringBuffer > String
场景:经常需要改变字符串内容时使用后面两个优先使用StringBuilder,多线程使用共享变量时使用StringBuffer
重载和重写的区别重载: 发生在同一个类中,方法名必

    推荐阅读