Java面试题附答案(面试必会)

Java面试题大全

    • JavaSE
      • 1.JDK和JRE区别
      • 2.八大数据类型
      • 3.equals和==区别
      • 4.String类的常用方法
      • 5.String不可变原理
      • 6.线程池三大方法,七大参数,四种拒绝策略
      • 7.ArrayList 和LinkedList 区别以及底层原理
      • 8.类的实例化顺序
      • 9.synchronized 和 ReentrantLock 区别是什么?
      • 10.HashMap底层原理(重点)
      • 11.HashMap的put(k,v)实现原理
      • 12.HashMap的get(k,v)实现原理
      • 13.Volatile
      • 14.线程几种状态,什么时候会阻塞
      • 15.为什么阿里巴巴Java手册不建议使用Executors创建线程池?
      • 16.类加载过程
      • 17.Java中final、finally、finalize的区别与用法
      • 18.java中String、StringBuffer和StringBuilder的区别
      • 19.线程安不安全指什么
      • 20.Session 与 Token 的区别
      • 21.java中四种修饰符的限制范围
      • 22.Object 类中的方法
      • 23.线程如何通信(面试常问)
      • 24.do while 和while的区别
      • 25.Continue和Break区别
      • 26. 面向对象的特征
      • 27.Java创建对象有几种方式?
      • 28. Java 中 IO 流分为几种?
      • 29.BIO、NIO、AIO 有什么区别?
    • 计算机网络
      • 1.TCP三次握手,四次挥手
      • 2.TCP和UDP区别以及长、短连接
      • 3.OSI七层模型和TCP/IP四层协议
      • 4.HTTP常见状态码
      • 5.进程三种状态
      • 6.进程和线程,进程可以没有线程吗
      • 7.从输入URL到页面展示的详细过程
    • JVM
      • g1 和 cms 区别
      • JVM内存模型以及GC算法
    • 数据库(MySql、Redis)
      • 1.数据库三种删除方式及其区别
      • 2.事务的隔离级别
      • 3.MYSQL的两种存储引擎区别(事务、锁级别等等),各自的适用场景
      • 4.索引的好处以及适合使用的场景
      • 5.最左匹配原则
      • 6.死锁怎么解决
      • 7.limit分页
      • 8. 分组查询,聚合函数
      • 9. where和having区别
      • 10.有哪些数据库优化方式(重点)
      • 11.索引
      • 12.数据库的三范式是什么(重要)
      • 13.SQL优化
      • 14.什么是内联接、左外联接、右外联接?
    • 数据结构
      • 数组和链表区别,单链表和双链表
      • 什么是红黑树
    • 版本管理工具(git)
      • git命令以及分区
    • 框架
      • 1.SpringMVC执行原理
      • 2.SpringBoot自动装配原理
      • 3.SpringBoot常用注解
      • 4.GET和POST的区别
      • 5.threadlocal原理以及内存泄漏怎么解决
      • 6.Spring中 bean生命周期
      • 7.Mybatis中的 ${} 和 #{}区别与用法
      • 8.什么是Nginx
      • 9. Nginx的应用场景
      • 10.什么是 JWT (JSON WEB TOKEN)
      • 11.MyBatis 与 Hibernate 有哪些不同?
      • 12.通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应, 这个 Dao 接口的工作原理是什么?Dao 接口里的方法, 参数不同时,方法能重载吗?
      • 13.Mybatis 的一级、二级缓存
      • 14.什么是 MyBatis 的接口绑定?有哪些实现方式?
      • 15.Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
      • 16.什么是 CSRF 攻击?
      • 17.RequestMapping 和 GetMapping 的不同之处在哪里?
    • 消息队列RabbitMQ
      • 1.什么是 rabbitmq,为什么要使用?
      • 2. rabbitmq 的使用场景
      • 3.如何避免消息重复投递或重复消费?
      • 4.消息基于什么传输?
      • 5.Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别?

JavaSE

1.JDK和JRE区别

JRE(Java Runtime Enviroment)是运行Java程序所必须环境的集合,包含JVM标准实现及 Java核心类库。它包括Java虚拟机、Java平台核心类和支持文件。它不包含开发工具(编译器、调试器等)。
JDK(Java Development Kit)是Java开发工具包,它提供了Java的开发环境(提供了编译器javac等工具,用于将java文件编译为class文件)和运行环境(提供了JVM和Runtime辅助包,用于解析class文件使其得到运行)。

2.八大数据类型

分别是byte, short, int, long, char, float, double, boolean.
1.byte
byte属于Java中的整型,长度为1字节8bit,取值10000000(-128)到 01111111(127),变量初始化默认值为0,包装类Byte

2.short
short属于Java中的整型,长度为2字节16bit,取值10000000 00000000(-32768)到 01111111 11111111(32767),变量初始化默认值为0,包装类Short

3.int
int属于Java中的整型,长度为4字节32bit,取值-2^31 (-2,147,483,648)到 2^31-1(2,147,483,647),变量初始化默认值为0,包装类Integer

4.long
long属于Java中的整型,长度为8字节 64bit,取值-2^63 (-9,223,372,036,854,775,808‬)到 2^63-1(9,223,372,036,854,775,8087),变量初始化默认值为0或0L,包装类Long
5.float
float属于Java中的浮点型,也叫单精度浮点型,长度为4字节 32bit,变量初始化默认值0.0f,包装类Float,取值2-128~2128
6.double
double属于Java中的浮点型,也叫双精度浮点型,长度为8字节 64bit,变量初始化默认值0.0d,包装类Double,取值2-1024~21024
7.char
char属于java中的字符型,占2字节 16bit,可以赋值单字符以及整型数值, 变量初始化无默认值,包装类Character。
如:
char a = ‘a’;
char a = ‘中’;
char a = 12; // 取值范围0~65536,因为char类型在ASCII字符编码中,有对应的数值,可直接做运算,输出字符表中对应的字符

8.boolean
在JVM中并没有提供boolean专用的字节码指令,而boolean类型数据在经过编译后在JVM中会通过int类型来表示,此时boolean数据4字节32位,而boolean数组将会被编码成Java虚拟机的byte数组,此时每个boolean数据1字节占8bit.
仅有两个值true, false,变量初始化默认值false

3.equals和==区别

对于==,一般比较的是值是否相等 如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等; 如果作用于引用类型的变量,则比较的是所指向的对象的地址

对于equals方法,一般为比较内容是否相同 如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址; 诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

4.String类的常用方法

  • public int length() //返回该字符串的长度
  • public char charAt(int index) //返回字符串中指定位置的字符;注意字符串中第一个字符索引是0,最后一个是length()-1。
  • public int compareTo(String anotherString) //该方法是对字符串内容按字典顺序进行大小比较,通过返回的整数值指明当前字符串与参数字符串的大小关系。若当前对象比参数大则返回正整数,反之返回负整数,相等返回0。
  • public String toLowerCase()//返回将当前字符串中所有字符转换成小写后的新串
  • public String toUpperCase()//返回将当前字符串中所有字符转换成大写后的新串
  • public String substring(int beginIndex)//该方法从beginIndex位置起,从当前字符串中取出剩余的字符作为一个新的字符串返回。

5.String不可变原理

String 被声明为 final,因此它不可被继承。(Integer 等包装类也不能被继承)
之所以设计成不可变,是为了安全,保证了线程安全,以及让常量池有意义
string不可变的设计出于性能考虑,当然背后的原理是string pool,当然string pool不可能使string类不可变,不可变的string更好的提高性能。

6.线程池三大方法,七大参数,四种拒绝策略

具体答案参考我之前的文章https://blog.csdn.net/JiaMing11_27/article/details/119078588?spm=1001.2014.3001.5501

7.ArrayList 和LinkedList 区别以及底层原理

ArrayList和LinkedList 都实现了list的接口,Al底层是数组,时间复杂度是O(1),Lk底层数据结构是双向循环链表 ,链表只有一个前驱和后继,时间复杂度O(n)
相对来说,Al是数组查找更容易,Lk因为是链表,所以插入、删除比较容易,但是更占内存,因为每一个节点存储了两个引用 ,一个指向前一个元素 一个后。

8.类的实例化顺序

父类静态代变量 父类静态代码块 子类静态变量 子类静态代码块
父类非静态变量 父类构造函数 子类非静态变量 子类构造

9.synchronized 和 ReentrantLock 区别是什么?

1.ReentrantLock 是 API 级别的,synchronized 是 JVM 级别的
2. ReentrantLock 可以实现公平锁
3 ReentrantLock 通过 Condition 可以绑定多个条件
4. 底层实现不一样, synchronized 是同步阻塞,使用的是悲观并发策略,lock 是同步非阻塞,采用的是乐观并发策略
5. Lock 是一个接口,而 synchronized 是 Java 中的关键字,synchronized 是内置的语言实现。
6. synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;
而 Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,
因此使用 Lock 时需要在 finally 块中释放锁。
7.通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。

10.HashMap底层原理(重点)

hashMap是线程不安全的,HashMap是数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,采用哈希表来存储的,hashMap是根据键的hashCode值存储数据,又很快的访问速度,但是遍历顺序不确定 hashMap是一对一或一对多的关系 键只允许有一个空值 value可以有多个 当键相同时 会覆盖掉value值
底层实现原理:
HashMap4种构造方法 指定初始大小和负载因子 指定初始大小和默认负载因子 都采用默认值 容量默认16 为了减少hash碰撞次数,折中,均匀泊松分布 。负载因子默认0.75 ,因为0.5 元素达到一半就扩容 扩容太浪费资源 ,查询效率会增加,但是空间利用率低 。1.0时空间利用率高了,但是耗费时间 。

11.HashMap的put(k,v)实现原理

(1)首先将k,v封装到Node对象当中(节点)。
(2)然后它的底层会调用K的hashCode()方法得出hash值。
(3)通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。

12.HashMap的get(k,v)实现原理

(1)先调用k的hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。
(2)通过上一步哈希算法转换成数组的下标之后,在通过数组下标快速定位到某个位置上。如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着K和单向链表上的每一个节点的K进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的K和参数K进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value。

13.Volatile

jvm提供的轻量级同步机制
三个特性:保证可见性 不保证原子性 禁止指令重排

14.线程几种状态,什么时候会阻塞

在Java当中,线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态;
第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,等待或者睡眠中回来之后,也会处于就绪状态
第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend等方法都可以导致线程阻塞。
第五是死亡状态。如果一个线程的run方法执行结束,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪状态。

15.为什么阿里巴巴Java手册不建议使用Executors创建线程池?

FixedThreadPool和SingleThreadExecutor => 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而引起OOM异常
CachedThreadPool => 允许创建的线程数为Integer.MAX_VALUE,可能会创建大量的线程,从而引起OOM异常,这就是为什么禁止使用Executors去创建线程池,而是推荐自己去创建ThreadPoolExecutor的原因。

16.类加载过程

JVM类加载机制定义:
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可被虚拟机直接使用的Java类型的过程

类从被加载到虚拟机内存中开始、到卸载出内存为止,整个生命周期包括七个阶段:

  • 加载
  • 验证
  • 准备
  • 解析
  • 初始化
  • 使用
  • 卸载

17.Java中final、finally、finalize的区别与用法

final:java中的关键字,修饰符。
A).如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被继承。因此,一个类不能同时被声明为abstract抽象类的和final的类。
B).如果将变量或者方法声明为final,可以保证它们在使用中不被改变.
  1)被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。
  2)被声明final的方法只能使用,不能重载。
  
finally:java的一种异常处理机制。
  finally是对Java异常处理模型的最佳补充。finally结构使代码总会执行,而不管无异常发生。使用finally可以维护对象的内部状态,并可以清理非内存资源。特别是在关闭数据库连接这方面,如果程序员把数据库连接的close()方法放到finally中,就会大大降低程序出错的几率。
  
finalize:Java中的一个方法名。
Java技术使用finalize()方法在垃圾收集器将对象从内存中清除出去前,做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没被引用时对这个对象调用的。它是在Object类中定义的,因此所的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。
finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。

18.java中String、StringBuffer和StringBuilder的区别

StringBuffer是线程安全,可以不需要额外的同步用于多线程中;

StringBuilder是非同步,运行于多线程中就需要使用着单独同步处理,但是速度就比StringBuffer快多了;

StringBuffer与StringBuilder两者共同之处:可以通过append、indert进行字符串的操作。

String实现了三个接口:Serializable、Comparable、CarSequence

StringBuilder只实现了两个接口Serializable、CharSequence,相比之下String的实例可以通过compareTo方法进行比较,其他两个不可以。

19.线程安不安全指什么

线程安全就是说多线程访问同一代码,不会产生不确定的结果。编写线程安全的代码是低依靠线程同步。

20.Session 与 Token 的区别

session生成方式?
浏览器第一次访问服务器,服务器会创建一个session,然后同时为该session生成一个唯一的会话的key,也就是sessionid,然后,将sessionid及对应的session分别作为key和value保存到缓存中,也可以持久化到数据库中,然后服务器再把sessionid,以cookie的形式发送给客户端。这样浏览器下次再访问时,会直接带着cookie中的sessionid。然后服务器根据sessionid找到对应的session进行匹配;
还有一种是浏览器禁用了cookie或不支持cookie,这种可以通过URL重写的方式发到服务器;

简单来讲,用户访问的时候说他自己是张三,他骗你怎么办? 那就在服务器端保存张三的信息,给他一个id,让他下次用id访问。
token的生成方式?
答:浏览器第一次访问服务器,根据传过来的唯一标识userId,服务端会通过一些算法,如常用的HMAC-SHA256算法,然后加一个密钥,生成一个token,然后通过BASE64编码一下之后将这个token发送给客户端;客户端将token保存起来,下次请求时,带着token,服务器收到请求后,然后会用相同的算法和密钥去验证token,如果通过,执行业务操作,不通过,返回不通过信息;

21.java中四种修饰符的限制范围

1.public 公共的 可以被所有其他类访问
2.private 私有的 只可以被自己访问和修改
3.protected 保护的 可以被自己,子类,同一包下的类可以访问
4.default 默认 同一包中的类可以访问

22.Object 类中的方法

(1)getclass 返回运行时类
我们写一段代码 不运行 会生成.java文件,这就是编译时类。运行时类是java文件经过编译变成.class文件,这些文件不能直接运行,交给JVM来解析运行。
(2)hashCode方法

该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。

一般必须满足obj1.equals(obj2) = =true。可以推出obj1.hash- Code()= =obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。
(3)equals 比较地址是否相同 相当于==
重写equals方法
(4)clone 返回当前对象的副本
克隆分为深克隆和浅克隆
对于一个类只有基本类型,那深克隆和浅克隆是一样的。如果有引用类型,则不同。

  • 深克隆 :新开辟内存空间,值拷贝
  • 浅克隆:拷贝的是引用

(5)toString
返回对象的字符串表示形式
线程安全就是说多线程访问同一代码,不会产生不确定的结果。编写线程安全的代码是低依靠线程同步。
(6)finalize方法
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。

(7)wait方法

wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。

调用该方法后当前线程进入睡眠状态,直到以下事件发生。

  • 其他线程调用了该对象的notify方法。
  • 其他线程调用了该对象的notifyAll方法。
  • 其他线程调用了interrupt中断该线程。
  • 时间间隔到了。

此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。

(8)notify方法
该方法唤醒在该对象上等待的某个线程。

(9)notifyAll方法
该方法唤醒在该对象上等待的所有线程。

23.线程如何通信(面试常问)

方式一:使用 volatile 关键字
基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想,大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。这也是最简单的一种实现方式
方式二:使用Object类的wait() 和 notify() 方法
众所周知,Object类提供了线程间通信的方法:wait()、notify()、notifyaAl(),它们是多线程通信的基础,而这种实现方式的思想自然是线程间通信。
方式三:使用JUC工具类 CountDownLatch
jdk1.5之后在java.util.concurrent包下提供了很多并发编程相关的工具类,简化了我们的并发编程代码的书写,***CountDownLatch***基于AQS框架,相当于也是维护了一个线程间共享变量state
方式四:使用 ReentrantLock 结合 Condition
方式五:基于LockSupport实现线程间的阻塞和唤醒

24.do while 和while的区别

while和do…while语句都是循环语句,功能都差不多,唯一的区别在于检验条件的时间上。while语句在进入循环体之前要先判断条件是否成立,如果成立的话则进入循环体。
而do…while语句则相反,是先执行循环体,然后再判断条件是否成立,如果成立的话则继续循环体,如果不成立则跳出循环,也就是说对于do…while语句,不管条件是否成立都要先执行一遍。

25.Continue和Break区别

break:while循环break是用于永久终止循环。即不执行本次循环中break后面的语句,直接跳出循环。

continue:while循环continue是用于终止本次循环。即本次循环中continue后面的代码不执行,进行下一次循环的入口判断。

26. 面向对象的特征

面向对象的编程语言有封装、继承 、抽象、多态等4个主要的特征。

封装: 把描述一个对象的属性和行为的代码封装在一个模块中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法可以直接访问同一个对象中的属性。
抽象: 把现实生活中的对象抽象为类。分为过程抽象和数据抽象 数据抽象 -->鸟有翅膀,羽毛等(类的属性) 过程抽象 鸟会飞,会叫(类的方法)
继承:子类继承父类的特征和行为。子类可以有父类的方法,属性(非private)。子类也可以对父类进行扩展,也可以重写父类的方法。缺点就是提高代码之间的耦合性。
多态:多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定(比如:向上转型,只有运行才能确定其对象属性)。方法覆盖和重载体现了多态性。

27.Java创建对象有几种方式?

java中提供了以下四种创建对象的方式:

  1. new创建新对象
  2. 通过反射机制
  3. 采用clone机制
  4. 通过序列化机制

28. Java 中 IO 流分为几种?

按功能来分:输入流(input)、输出流(output)。

按类型来分:字节流和字符流。

字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。

29.BIO、NIO、AIO 有什么区别?

BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

计算机网络

1.TCP三次握手,四次挥手

具体答案参考之前博客https://blog.csdn.net/JiaMing11_27/article/details/119651072?spm=1001.2014.3001.5501

2.TCP和UDP区别以及长、短连接

具体答案参考之前博客https://blog.csdn.net/JiaMing11_27/article/details/119651846?spm=1001.2014.3001.5501

3.OSI七层模型和TCP/IP四层协议

Java面试题附答案(面试必会)_第1张图片

4.HTTP常见状态码

答案看我之前博客https://blog.csdn.net/JiaMing11_27/article/details/118436439?spm=1001.2014.3001.5501

5.进程三种状态

进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。
进程状态:
一般来说,进程有三个状态,即就绪状态,运行状态,阻塞状态
Java面试题附答案(面试必会)_第2张图片

6.进程和线程,进程可以没有线程吗

程序至少有一个进程,进程至少有一个线程
线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。

7.从输入URL到页面展示的详细过程

1、输入网址
2、DNS解析
3、建立tcp连接
4、客户端发送HTTP请求
5、服务器处理请求 
6、服务器响应请求
7、浏览器展示HTML
8、浏览器发送请求获取其他在HTML中的资源。

JVM

g1 和 cms 区别

吞吐量优先和响应优先的垃圾收集器选择。
Cms是以获取最短回收停顿时间为目标的收集器。基于标记-清除算法实现。比较占用cpu资源,切易造成碎片。
G1是面向服务端的垃圾收集器,是jdk9默认的收集器,基于标记-整理算法实现。可利用多核、多cpu,保留分代,实现可预测停顿,可控。

JVM内存模型以及GC算法

参考之前博客:https://blog.csdn.net/JiaMing11_27/article/details/119044707?spm=1001.2014.3001.5501

数据库(MySql、Redis)

1.数据库三种删除方式及其区别

1. 使用delete 语句

特点:

  • delete 属于数据库操纵语言DML,表示删除表中的数据,删除过程是每次从表中删除一行,并把该行删除操作作为事务记录在日志中保存

  • 可以配合事件(transaction)和 回滚(rollback)找回数据,且自增不会被重置

  • delete 既可以对table也可以对view

  • 可以全部删除,也可以按条件删除

2. 使用truncate 语句

特点:

  • truncate 属于数据库定义语言DDL,表示删除表中所有数据,DDL操作是隐性提交的!不能rollback
  • truncate一次性的从表中删除所有数据,不会保存到日志中,相当于直接删除整个表,再重新创建一个一模一样的表
  • 使用truncate 删除的数据不能恢复
  • truncate 只能对table,执行速度快

3.使用drop语句

特点:

  • drop 属于数据库定义语言DDL,表示删除表, 也可以用来删除数据库

2.事务的隔离级别

多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题*存在问题:
1.脏读:一个事务,读取到另一个事务中没有提交的数据

2.不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。
3,幻读:一个事务操作(DNL)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。

隔离级别:

  1. read uncommitted :读未提交
    *产生的问题:脏读、不可重复读、幻读2. read committed :读已提交(oracle)*产生的问题:不可重复读、幻读
  2. repeatable read :可重复读(MysQL默认)*产生的问题:幻读
  3. serializable :串行化
    *可以解决所有的问题
    *注意:隔离级别从小到大安全性越来越高,但是效率越来越低

教据库查询隔离级别:
select @@tx_isolation;
数据库设置隔离级别:
set global transaction isolation level级别字符串;

3.MYSQL的两种存储引擎区别(事务、锁级别等等),各自的适用场景

引擎 特性
MYISAM 不支持外键,表锁,插入数据时,锁定整个表,查表总行数时,不需要全表扫描
INNODB 支持外键,行锁,查表总行数时,全表扫描

4.索引的好处以及适合使用的场景

索引最大的好处是提高查询速度,
缺点是更新数据时效率低,因为要同时更新索引
对数据进行频繁查询进建立索引,如果要频繁更改数据不建议使用索引。

5.最左匹配原则

最左匹配原则是针对索引的
举例来说:两个字段(name,age)建立联合索引,如果where age=12这样的话,是没有利用到索引的,
这里我们可以简单的理解为先是对name字段的值排序,然后对age的数据排序,如果直接查age的话,这时就没有利用到索引了,
查询条件where name=‘xxx’ and age=xx 这时的话,就利用到索引了,再来思考下where age=xx and name=’xxx‘ 这个sql会利用索引吗,
按照正常的原则来讲是不会利用到的,但是优化器会进行优化,把位置交换下。这个sql也能利用到索引了

6.死锁怎么解决

找到进程号,kill掉即可!

7.limit分页

limit 【索引】【一页多少条数据】

例如:
#第二页 每页3条数据
limit 3 3

8. 分组查询,聚合函数

group by+字段 实现按字段分组查询
聚合函数有 count,min,max,average 等等

9. where和having区别

where:

  • where是一个约束声明,使用where来约束来自数据库的数据;
  • where是在结果返回之前起作用的;
  • where中不能使用聚合函数。

having:

  • having是一个过滤声明;
  • 在查询返回结果集以后,对查询结果进行的过滤操作;
  • 在having中可以使用聚合函数。

10.有哪些数据库优化方式(重点)

推荐一篇文章,写的很好!
https://www.zhihu.com/question/36431635

11.索引

索引(Index)是帮助 MySQL 高效获取数据的数据结构。 常见的查询算法,顺序查找,二分查找,二叉排序树查找,哈希散列法,分块查找,平衡多路搜索树 B 树(B-tree ),索引是对数据库表中一个或多个列的值进行排序的结构,建立索引有助于快速获取信息。

mysql 有4种不同的索引:

  • 主键索引(PRIMARY)
  • 唯一索引(UNIQUE)
  • 普通索引(INDEX)
  • 全文索引(FULLTEXT)
    索引并非是越多越好,创建索引也需要耗费资源,一是增加了数据库的存储空间,二是在插入和删除时要花费较多的时间维护索引

索引加快数据库的检索速度索引降低了插入、删除、修改等维护任务的速度唯一索引可以确保每一行数据的唯一性通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能索引需要占物理和数据空间

12.数据库的三范式是什么(重要)

第一范式:列不可再分
第二范式:行可以唯一区分,主键约束
第三范式:表的非主属性不能依赖与其他表的非主属性 外键约束且三大范式是一级一级依赖的,第二范式建立在第一范式上,第三范式建立第一第二范式上 。

13.SQL优化

1、查询语句中不要使用select *
2、尽量减少子查询,使用关联查询(left join,right join,inner join)替代
3、减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代
4、or 的查询尽量用 union或者union all 代替(在确认没有重复数据或者不用剔除重复数据时,union all会更好)
5、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
6、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0

14.什么是内联接、左外联接、右外联接?

内联接(Inner Join):匹配2张表中相关联的记录。
左外联接(Left Outer Join):除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录,右表中未匹配到的字段用NULL表示。
右外联接(Right Outer Join):除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录,左表中未匹配到的字段用NULL表示。在判定左表和右表时,要根据表名出现在Outer Join的左右位置关系

数据结构

数组和链表区别,单链表和双链表

数组静态分配内存,链表动态分配内存;数组在内存中连续,链表不连续;数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n);数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。
数组优点:
随机访问性强(通过下标进行快速定位)
查找速度快
数组缺点:
插入和删除效率低(插入和删除需要移动数据)
可能浪费内存(因为是连续的,所以每次申请数组之前必须规定数组的大小,如果大小不合理,则可能会浪费内存)
内存空间要求高,必须有足够的连续内存空间。
数组大小固定,不能动态拓展

链表的优点:
插入删除速度快(因为有next指针指向其下一个节点,通过改变指针的指向可以方便的增加删除元素)
内存利用率高,不会浪费内存(可以使用内存中细小的不连续空间(大于node节点的大小),并且在需要空间的时候才创建空间)
大小没有固定,拓展很灵活。
链表的缺点:
不能随机查找,必须从第一个开始遍历,查找效率低

单链表:
在这里插入图片描述
双链表:
Java面试题附答案(面试必会)_第3张图片

为什么市场上单链表的使用多于双链表呢?

从存储结构来看,每个双链表的节点要比单链表的节点多一个指针,而长度为n就需要
n*length(这个指针的length在32位系统中是4字节,在64位系统中是8个字节)
的空间,这在一些追求时间效率不高应用下并不适应,因为它占用空间大于单链表所占用的空间;这时设计者就会采用以时间换空间的做法,这时一种工程总体上的衡量。

什么是红黑树

推荐一篇文章,用图的方式理解红黑树,非常生动形象!
https://blog.csdn.net/qq_36610462/article/details/83277524

版本管理工具(git)

git命令以及分区

参考我之前博客:https://blog.csdn.net/JiaMing11_27/article/details/119141032?spm=1001.2014.3001.5501

框架

1.SpringMVC执行原理

参考博客:https://blog.csdn.net/JiaMing11_27/article/details/116609811?spm=1001.2014.3001.5501

2.SpringBoot自动装配原理

参考博客:https://blog.csdn.net/JiaMing11_27/article/details/116610872?spm=1001.2014.3001.5501

3.SpringBoot常用注解

1、@SpringBootApplication

包含@Configuration、@EnableAutoConfiguration、@ComponentScan

通常用在主类上。

2、@Repository

用于标注数据访问组件,即DAO组件。

3、@Service

用于标注业务层组件。

4、@RestController

用于标注控制层组件(如struts中的action),包含@Controller和@ResponseBody

5、@ResponseBody

表示该方法的返回结果直接写入HTTP response body中

一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析

为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。

6、@Component

泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

7、@ComponentScan

组件扫描。相当于,如果扫描到有@Component @Controller @Service等这些注解的类,则把

这些类注册为bean。

8、@Configuration

指出该类是 Bean 配置的信息源,相当于XML中的,一般加在主类上。

9、@Bean

相当于XML中的,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。

10、@EnableAutoConfiguration

让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置,一般加在主类上。

11、@AutoWired

byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
当加上(required=false)时,就算找不到bean也不报错。

12、@Qualifier

当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用

13、@Resource(name=“name”,type=“type”)

没有括号内内容的话,默认byName。与@Autowired干类似的事。

14、@RequestMapping

RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

4.GET和POST的区别

Java面试题附答案(面试必会)_第4张图片
以上来自W3cSchool

5.threadlocal原理以及内存泄漏怎么解决

ThreadLocal主要为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。一个线程可以储存多个ThreadLocal的值
key使用软引用解决了ThreadLocal对象本身的内存泄漏问题,使用remove方法解决了Entry的value的内存泄漏问题。

6.Spring中 bean生命周期

Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化

Bean实例化后对将Bean的引入和值注入到Bean的属性中

如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法

如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入

如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。

如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。

如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用

如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。

此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。

如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

7.Mybatis中的 ${} 和 #{}区别与用法

#{} 这种取值是编译好SQL语句再取值
${} 这种是取值以后再去编译SQL语句

#{}方式能够很大程度防止sql注入。
$方式无法防止Sql注入。
KaTeX parse error: Expected 'EOF', got '#' at position 27: …对象,例如传入表名. 一般能用#̲的就别用.

8.什么是Nginx

Nginx是一个http服务器。是一个使用c语言开发的高性能的http服务器及反向代理服务器。Nginx是一款高性能的http
服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。由俄罗斯的程序设计师IgorSysoev所开发,官方测试nginx能够支支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定。

9. Nginx的应用场景

  1、 http服务器。Nginx是一个http服务可以独立提供http服务。可以做网页静态服务器。

  2、 虚拟主机。可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。
  
  3、 反向代理,负载均衡。
  当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。

10.什么是 JWT (JSON WEB TOKEN)

为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC
7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

分为三部分:

  • 头部(header)
  • 载荷(payload, 类似于飞机上承载的物品)
  • 签证(signature)

jwt是SpringSucurity框架中的,内容不多,相对来说视频理解起来更轻松,推荐一个讲的很好的课程,可以更好地理解JWT。
https://www.bilibili.com/video/BV1pr4y1F7bC?from=search&seid=8590849621746951843

11.MyBatis 与 Hibernate 有哪些不同?

1、Mybatis 和 hibernate 不同,它不完全是一个 ORM 框架,因为 MyBatis 需要程序员自己编写 Sql 语句。
2、Mybatis 直接编写原生态 sql,可以严格控制 sql
执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需求变化要求迅速输出成果。但是灵活的前提是
mybatis 无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套 sql 映射文件,工作量大。
3、Hibernate 对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用 hibernate
开发可以节省很多代码,提高效率。

12.通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应, 这个 Dao 接口的工作原理是什么?Dao 接口里的方法, 参数不同时,方法能重载吗?

Dao 接口即 Mapper 接口。接口的全限名,就是映射文件中的 namespace 的值;
接口的方法名,就是映射文件中 Mapper 的 Statement 的 id 值;
接口方法内的参数,就是传递给 sql 的参数。
Mapper 接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符
串作为 key 值,可唯一定位一个 MapperStatement。在 Mybatis 中,每一个
标签,都会被解析为一个MapperStatement 对象。

举例:com.mybatis3.mappers.StudentDao.findStudentById,
可以唯一找到 namespace 为 com.mybatis3.mappers.StudentDao 下面 id 为findStudentById 的 MapperStatement。

Mapper 接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻
找策略。
Mapper 接口的工作原理是 JDK 动态代理,Mybatis 运行时会使用 JDK
动态代理为 Mapper 接口生成代理对象 proxy,代理对象会拦截接口方法,转而执行 MapperStatement 所代表的 sql,然后将 sql 执行结果返回。

13.Mybatis 的一级、二级缓存

1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

14.什么是 MyBatis 的接口绑定?有哪些实现方式?

接口绑定,就是在 MyBatis 中任意定义接口,然后把接口里面的方法和 SQL 语句绑定, 我们直接调用接口方法就可以,这样比起原来了 SqlSession 提供的方法我们可以有更加灵活的选择和设置。
接口绑定有两种实现方式:
一种是通过注解绑定,就是在接口的方法上面加上@Select、@Update 等注解,里面包含 Sql 语句来绑定;
另外一种就是通过 xml里面写 SQL 来绑定, 在这种情况下,要指定 xml 映射文件里面的 namespace 必须为接口的全路径名。

当 Sql 语句比较简单时候,用注解绑定, 当 SQL 语句比较复杂时候,用 xml 绑定,一般用 xml 绑定的比较多。

15.Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下3 个注解:
@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。@ComponentScan:Spring组件扫描

16.什么是 CSRF 攻击?

CSRF 代表跨站请求伪造。这是一种攻击,迫使最终用户在当前通过身份验证的Web 应用程序上执行不需要的操作。CSRF 攻击专门针对状态改变请求,而不是数据窃取,因为攻击者无法查看对伪造请求的响应。

17.RequestMapping 和 GetMapping 的不同之处在哪里?

RequestMapping 具有类属性的,可以进行 GET,POST,PUT 或者其它的注释中具有的请求方法。GetMapping 是 GET 请求方法中的一个特例。
它只是 ResquestMapping 的一个延伸,目的是为了提高清晰度。

消息队列RabbitMQ

1.什么是 rabbitmq,为什么要使用?

Java面试题附答案(面试必会)_第5张图片

采用 AMQP 高级消息队列协议的一种消息队列技术,最大的特点就是消费并不需要确保提供方存在,实现了服务之间的高度解耦。

  • 在分布式系统下具备异步,削峰,负载均衡等一系列高级功能;
  • 拥有持久化的机制,进程消息,队列中的信息也可以保存下来。
  • 实现消费者和生产者之间的解耦。
  • 对于高并发场景下,利用消息队列可以使得同步访问变为串行访问达到一定量的限流,利于数据库的操作。
  • 可以使用消息队列达到异步下单的效果,排队中,后台进行逻辑下单。

2. rabbitmq 的使用场景

  • 服务间异步通信
  • 顺序消费
  • 定时任务
  • 请求削峰

3.如何避免消息重复投递或重复消费?

在消息生产时,MQ 内部针对每条生产者发送的消息生成一个 inner-msg-id,作为去重的依据(消息投递失败并重传),避免重复的消息进入队列;
在消息消费时,要求消息体中必须要有一个 bizId(对于同一业务全局唯一,如支付 ID、订单 ID、帖子 ID 等)作为去重的依据,避免同一条消息被重复消费。

4.消息基于什么传输?

由于 TCP 连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。
RabbitMQ使用信道的方式来传输数据。信道是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制

5.Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别?

对于吞吐量来说kafka和RocketMQ支撑高吞吐,ActiveMQ和RabbitMQ比他们低一个数量级。对于延迟量来说RabbitMQ是最低的。
1.从社区活跃度按照目前网络上的资料,RabbitMQ 、activeM 、ZeroMQ 三者中,综合来看,RabbitMQ 是首选。
2.持久化消息比较ActiveMq 和RabbitMq 都支持。持久化消息主要是指我们机器在不可抗力因素等情况下挂掉了,消息不会丢失的机制。
3.综合技术实现可靠性、灵活的路由、集群、事务、高可用的队列、消息排序、问题追踪、可视化管理工具、插件系统等等。RabbitMq / Kafka 最好,ActiveMq 次之,ZeroMq 最差。当然ZeroMq 也可以做到,不过自己必须手动写代码实现,代码量不小。尤其是可靠性中的:持久性、投递确认、发布者证实和高可用性。
4.高并发毋庸置疑,RabbitMQ 最高,原因是它的实现语言是天生具备高并发高可用的erlang 语言。
5.比较关注的比较, RabbitMQ 和 KafkaRabbitMq 比Kafka 成熟,在可用性上,稳定性上,可靠性上, RabbitMq 胜于 Kafka (理论上)。另外,Kafka 的定位主要在日志等方面, 因为Kafka 设计的初衷就是处理日志的,可以看做是一个日志(消息)系统一个重要组件,针对性很强,所以 如果业务方面还是建议选择 RabbitMq 。还有就是,Kafka 的性能(吞吐量、TPS )比RabbitMq 要高出来很多

持续更新!!!
时间匆忙,如果有错误欢迎指出,有什么缺少的也可以私信我,我会及时补充
创作不易,点个赞再走吧,你的支持是我创作的最大动力,谢谢!

你可能感兴趣的:(面经,java,面试)