Java 八股文总结

Java 八股文总结

彼方 56 2022-04-01

Java 面试八股文总结

1.接口和抽象类的区别

共同点:

  • 都不能被实例化
  • 都可以包含抽象方法
  • 都可以有默认实现的方法

不同点:

  • 接口主要是对类的行为进行约束;抽象类主要用于代码复用,强调的是所属关系
  • 一个类只能继承于一个类,但可以实现多个接口
  • 接口中的成员变量只能是public static final类型的,不能被修改且必须有初始值;抽象类的成员变量默认为default,可在子类中重写定义,也可重写赋值

2. 深拷贝和浅拷贝的区别

浅拷贝只是增加了一个指针指向已存在的内存地址

深拷贝是增加了一个指针同时申请了一块新的内存,使这个增加的指针指向这块新的内存

3. String为什么不可变

JDK9之前,Strign的底层是char型数组,JDK9之后调整为byte数组

  • 保存字符串的数组被声明为私有的且被final修饰,而且String类没有提供修改字符串的方法
  • String类被final修饰导致其不能被继承,从而避免了子类破坏String不可变

3.1 字符型常量和字符串常量的区别?

  • 字符型常量使用单引号引起一个字符,字符串常量使用双引号引起若干个字符
  • 字符型常量只占两个字节,字符串常量占若干个字节
  • 字符型常量相当于一个整型值(ASCII),字符串常量代表一个地址值

4. String、StringBuffer、StringBuilder的区别

  • 可变性
    • String对象不可变(原因如上)
    • StringBuffer和StringBuilder都继承于AbstratStringBuilde类,这个类也是使用字符数组保存字符串,但没有使用final和private修饰,而且这个类还提供了很多修改字符串的方法
  • 线程安全性
    • String中的对象是不可变的,可以理解为常量,线程安全
    • StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的
    • StringBuilder没有对方法添加同步锁,所以是线程不安全的
  • 性能
    • 每次对String类型进行改变的时候,都会生产一个新的String对象,性能较低。StringBuffer和StringBuilder都是对原对象本身进行操作,性能较高。

5. 字符串常量池

JVM为了提升性能和减少内存消耗针对字符串专门开辟的一块区域,主要是为了避免字符串的重复创建。

JDK7之前字符串常量池在方法区中,之后拿到了堆中。

6. 什么是泛型?泛型擦除?常用的通配符?

  • 泛型是JDK5引入的一个新特性,提供了编译时类型安全检测机制,确保在泛型类型上只能使用正确的类型的对象。

  • 泛型擦除:Java在运行期间,所有的泛型信息都会被擦除,只保留原始类型。

  • 常用通配符

    • T(type):标识一个确定的类型
    • ?:表示不确定的java类型
    • K V (key,value):分别代表java中的key和value
    • E(element):在集合中使用,因为集合中存放的是元素

7. Exception和Error的区别

  • Exception:程序本身可以处理的异常,可以通过catch来解决。可以分为Cheked Exception和UnChecked Exception(可以不处理)
  • Error:程序无法处理的错误,出现时Jvm一般会选中终止线程

8. Finally中可以使用return吗?

不可以,当try语句和finally语句中都使用了return语句时,try语句中的return会被忽略。try语句中的return返回值会被暂存到一个本地变量中,当执行到finally语句中的return之后,这个本地变量的值就变成了finally语句中的return返回值。

9. Finally中的代码一定会执行吗?

不一定:

  • Finally执行之前,java虚拟机被终止运行的话,finally就不会执行
  • 程序所在的线程死亡,finally也不会执行
  • 关闭CPU

10. 序列化与反序列化

  • 序列化:将数据结构或对象转换成二进制字节流的过程
  • 反序列化:将在序列化过程中生成的二进制字节流转换为数据结构或者对象的过程

11. IO流分为几种?

  • 按流向分:输入流和输出流
  • 按操作单元分:字节流(无缓冲区 inputStream和outPutStream)和字符流(自带缓冲区 Reader和Writer)
  • 按流的角色分:节点流(直接操作数据读写的流类)和处理流( 是对一个已存在的的连接和封装,通过所封装的流的功能调用实现数据读写。)

12. IO流的特性?

  • 先进先出:最先写入输出流的数据最先被输入流读取到
  • 顺序存取:写入和读取都可以按顺序进行,但不可以随机访问中间的数据
  • 只读或只写:输入流只能进行都操作,输出流只能进行写操作

13. Java中的容器有哪些?分别有什么区别?

  • List:存储的元素是有序、可重复的
  • Set:存储的元素是无序、不可重复的
  • Queue:存储的元素是有序、可重复的
  • Map:使用键值对存储,key是无序、不可重复的,value是无序、可重复的

14. 集合框架底层数据结构

  • List
    • ArrayList:数组
    • Vector(古老实现):数组
    • LinkedList:双向链表
  • Set
    • HashSet(无序、唯一):底层使用HashMap来保存元素
    • LinkedHashSet:HashSet的子类,使用HashMap实现
    • TreeSet(有序,唯一):红黑树
  • Queue
    • PriorityQueue:数组实现二叉堆
    • ArrayQueu:数组+双指针
  • Map
    • HashMap:数组+链表+红黑树
    • LinkedHashMap:HashMap的子类,在HashMap的基础上,增加了一条双向链表
    • Hashtable:数组+链表
    • TreeMap:红黑树(自平衡的排序二叉树)

15. ArrayList和LinkedList的区别

  • 底层数据结构不同:ArrayList底层是数组,LinkedList底层是双向链表
  • 是否支持快速随机访问:ArrayList支持高效的随机元素访问,而LinkedList不支持
  • 插入和删除是否受元素位置的影响:ArrayList受影响,LinkedList不受影响

16. Comparable与Comparator的区别

  • Comparable是lang包下的一个接口,它有一个compareTo(Object object)方法
  • Comparator是java.util包下的一个接口,它有一个compare(Object object1,Object object2)方法来排序

17. 什么是死锁?解决方式?

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或彼此通信而造成的一种堵塞现象。

产生死锁的4个必要条件:

  • 互斥条件:一个资源每一次只能被一个进程使用
  • 请求与保持条件:一个进程因请求资源阻塞时,不释放已获得的资源
  • 不剥夺条件:进程已获得的资源,在使用完之前,不能强行剥夺
  • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系

18. 什么是进程和线程?

进程:CPU执行单个任务的过程,是程序在执行过程中CPU资源分配的最小单位

线程:是CPU调度的最小单位,它可以和属于同一个进程的其他线程共享这个进程的全部资源

协程:是一种用户态的轻量级线程,协程的调度由用户控制。

关系:一个进程包含多个线程,一个线程只能在一个进程中,每一个进程最少包含一个线程

19. 并行与并发

并行:单位时间内,多个任务同时执行

并发:同一时间段,多个任务都在执行

20. Synchronized

synchronized是为了解决多个线程之间访问资源的同步性,它可以保证被修饰的方法或者代码块任意时间只能有一个线程执行

三种使用方式:

  • 修饰静态方法(当前类加锁)
  • 修饰实例方法(当前对象实例加锁)
  • 修饰代码块(指定加锁对象,对给定对象或类加锁)

21. Synchronized和Volatile的区别

  • volatile是线程同步的轻量级实现,性能要比synchronized要好,但是只能用于变量
  • volatile只能保持数据的可见性,不能保持数据的原子性。synchronized都可以保证
  • volatile主要解决变动在多个线程之间的可见性。synchronized解决的是多个线程之间访问资源的同步性。

22. Synchronized和ReentrantLock的区别

  • 两者都是可重入锁
  • Synchronized依赖于JVM而ReentrantLock依赖于API
  • ReentrantLock比Synchronized增加了一些高级功能

23. ThreadLocal类

实现每个线程都有自己的专属本地变量,避免了线程安全问题。

24. 使用线程池的好处

  • 降低资源消耗
  • 提升响应速度
  • 提高线程的可管理性

25. Runable接口和Callable接口的区别

Runnable不会返回结果或抛出异常提示,Callable接口可以

26. Execute()和Submit()方法的区别

  • execute()用于提交不需要返回值的任务,所以无法判断任务是否被线程池成功执行
  • submit()用于提交需要返回值的任务,线程池会返回要给Future类型对象,通过这个对象可以判断任务是否执行成功

27. 如何创建线程池

  • 通过ThreadPoolExecutor构造方法实现
  • 通过Executor框架的工具类Executors实习

28. AQS原理

AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,就需要一套线程阻塞等待以及被唤醒时锁分配的机制,将暂时获取不到锁的线程加入队列中。

29. Drop、Delete、Truncate的区别

Drop:直接将表删除

Delete:删除某一列数据

Truncate:清空表数据时使用

30. Mysql存储引擎

  • InnoDB
  • MyISAM
  • Memory
  • Archive

31. InnoDB和MyISAM的区别

  • 是否支持行级锁:InnoDB支持行级锁和表级锁,MyISAM支持表级锁
  • 是否支持事务:InnoDB支持事务,MyISAM不支持事务
  • 是否支持外键:InnoDB支持外键,MyISAM不支持
  • 是否支持数据库异常崩溃之后的安全恢复:InnoDB支持,MyISAM不支持

32. 事务的特性

  • 原子性:事务是最小的执行的单位,不允许分隔
  • 一致性:执行事务前后,数据保持一致
  • 持久性:并发事务之间数据库是独立的
  • 隔离性:一个事务被提交之后,它对数据库中数据的改变是持久的

33. 并发事务的问题

  • 脏读:
  • 幻读:
  • 不可重复读:
  • 丢失修改:

34. 事务的隔离级别与传播属性

隔离级别(5种):

  • DEFAULT:默认隔离级别,使用数据库默认的事务隔离级别

  • READ-UNCOMMITTED(读未提交):最低的隔离级别,可能导致脏读、幻读或不可重复读

  • READ-COMMITTED(读已提交):允许读取并发事务已提交的数据,可以阻止幻读

  • MySQL默认隔离级别REPEATABLE-READ(可重复读):对于同一个字段的多次读取结果都是一致的,可以阻止脏读和不可重复读

  • SERIALIZABLE(可串行化):最高隔离级别,所有事务依次逐个执行,可以避免脏读、幻读、不可重复读

传播属性(7种):

  • PROPAGATION_REQUIRED——支持当前事务,如果当前没有事务,就新建一个事务
  • PROPAGATION_SUPPORTS——支持当前事务,如果当前没有事务,就以非事务方式执行
  • PROPAGATION_MANDATORY——支持当前事务,如果当前没有事务,就抛出异常
  • PROPAGATION_REQUIRES_NEW——新建事务,如果当前存在事务,则把当前事务挂起
  • PROPAGATION_NOT_SUPPORTED——以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
  • PROPAGATION_NEVER——以非事务方式执行,如果当前存在事务,则抛出异常
  • PROPAGATION_NESTED——如果当前存在事务,则在嵌套事务内执行。如果没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

35. 什么是索引?优缺点?

索引是一种用于快速查询和检验数据的数据结构,常见的索引结构为:B树,B+树和Hash

优点:

  • 大大加快数据的检索速度
  • 通过创建唯一性索引,可以保证数据表中的每一行数据的唯一性

缺点:

  • 创建和维护索引需要耗费很多时间
  • 索引需要使用物理文件空间存储,会消耗一定空间

36. MySQL的索引类型

  • 普通索引
  • 唯一索引
  • 主键索引
  • 组合索引
  • 全文索引

37. 创建索引的方式

  • 新建表中添加索引
  • 已建表中添加索引
  • 以修改表的方式添加索引

38. Spring模块

  • Spring Core
  • Spring Aspects
  • Spring AOP
  • Spring Web
  • Spring Test
  • Spring DataAccess

39. IOC(Inverse of control)

IOC(控制反转),是一种设计思想,是将程序中原本手动创建对象的权力交给spring框架管理

控制:创建对象的权力

反转:控制器交给外部环境

40. DI(Dependency Injection)

DI(依赖注入)是IOC最常见也是最合理的实现方式

41. AOP(Aspect Oriented Programming)

AOP(面向切面编程):能够将那些与业务无关,但却为业务模块所共同调用的逻辑封装起来,便于减少系统的重复代码,降低模块之间的耦合性

42. SpringAOP 和 AspectAOP的区别

SpringAOP:运行时增强,基于动态代理
AspectAOP:编译时增强,基于字节码操作


# Java