Java面试点 -【笔记】
1. HashMap实现原理,HashTable,ConcurrentHashMap,TreeMap相关内容. ArrayList,Vector,HashSet,TreeSet
- HashMap 基于哈希表的实现 底层使用数组与链表实现,放入数据时首先计算key的hashCode,根据(hashCode%数组长度)将数据放入余数所对应的数组下标的链表里面(java8中引入了红黑树的概念,当链表的长度到8时,将单向链表转成红黑树,提高map的效率),HashMap的默认数组为16,扩容为2的整数次幂
- HashTable 基于哈希表的实现,key,value不允许出现null hashtable中的方法是Synchronize的,所以是线程安全的,默认容量11,扩容方式(old*2+1)
- ConcurrentHashMap 基于哈希表的实现,是线程安全的,JDK1.8之前使用Segment分段锁机制,JDK1.8开始利用CAS+Synchronized来保证并发更新的安全,CAS是指compareAndSwap(native)方法
- HashSet 是无序的集合,不允许有重复的值,底层使用hashMap实现,set的值作为key,value是一个共用的Object对象
- TreeMap基于红黑树的实现,value可以是null,key不可为null
- TreeSet也是用TreeMap实现的
- Vector 是线程安全的,在底层数组不够用的时候,是在原来的基础上扩展1倍 关键性的方法,都添加synchronized关键字
- ArrayList 不是线程安全的,在底层数组不够用的时候,是在原来的基础上扩展0.5倍
- Synchronized关键字,尝试获取对象的锁,如果获取成功,计数器+1 释放时,计数器-1 为0时,表示当前对象锁没有被人持有 monitorenter和monitorexit字节码指令是实现原理
2. String相关
- 不是基本数据类型,String是不可变的,考虑到安全,性能,多线程。所以设计为不可变类。JVM使用字符串池来存储所有的字符串对象
- String 是不可变类,每当我们对String进行操作的时候,总是会创建新的字符串。操作String很耗资源,所以有StringBuffer和StringBuilder两个可变类操作String,StringBuffer是线程安全的,StringBuilder则不是线程安全的。StringBuilder的效率比StringBuffer高
3. JAVA8新特性
- 函数式接口,指仅包含一个抽象方法的接口,@FunctionalInterface 此注解限定接口为函数式接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。,所以你也可以给你的函数式接口添加默认方法
- 接口的默认方法,默认方法不算抽象方法,但是需要使用default关键字声明
- Lambda 表达式,简化匿名对象,只能适用于函数式接口,可以把Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递,符合函数式接口的定义),Lambda表达式无法访问到默认方法。
- 允许使用多重注解,指同一个注解可以注解多次,在此注解声明时需要声明一个注解容器存放此注解,并声明此注解是可以重复的注解
- stream流 ,是API中的一个新成员,它允许你以声明性方式处理数据集合
4. SpringMVC工作原理
- 客户端发送请求到DispatcherServlet
- DispatcherServlet查询handlerMapping找到处理请求的Controller
- Controller调用业务逻辑后,返回ModelAndView
- DispatcherServlet查询ModelAndView 找到指定视图
- 视图将结果返回到客户端
-SpringMVC流程
a. 用户发送请求到控制器DispatcherServlet
b. DispatcherServlet 收到请求调用HandlerMapping处理器映射
c. 处理器映射器找到具体的处理器,生成处理器对象和处理器拦截器返回给DispatcherServlet
d. DispatcherServlet调用HandlerAdapter处理器适配器
e. HandlerAdapter经过适配调用具体的处理器Controller
f. Controller执行完返回ModelAndView
g. HandlerAdapter 将controller执行结果ModelAndView返回给DispatcherServlet
h. DispatcherServlet 将ModelAndView传给ViewReslover视图解析器
i. ViewReslover 解析后返回具体的View
j. DispatcherServlet 根据View进行渲染视图
k. DispatcherServlet响应用户
5. Spring相关,IoC,AOP,动态代理
- IoC 控制反转,SpringServlet管理所有的Bean创建,依赖注入方式(基于注解的注入方式,set注入方式,构造器注入方式,静态工厂注入方式),实现IOC的主要设计模式就是工厂模式
- AOP 面向切面编程(将一些与主业务无关,却为业务模块所共同调用的逻辑封装起来统一实现,便于减少系统重复代码,降低模块之间的耦合度。一般应用与权限控制,事务管理,日志记录,参数校验,签名校验,异常处理,性能统计等),实现AOP的主要设计模式是动态代理方式(代理模式是用户通过代理对象访问目标对象,静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同的父类,典型代表Aspect)
- 动态代理,Spring动态代理有两种,a. JDK的动态代理(JDK动态代理的两个核心接口是InvocationHandler和Proxy,是利用JDKAPI,动态的在内存中构建代理对象,需要我们指定创建代理对象实现的接口的类型,代理对象不需要实现接口,但是目标对象需要实现接口),b. cglib动态代理(cglib动态代理的两个核心接口是MethodInterceptor和Enhancer,cglib代理也叫做子类代理,是在内存中动态构建一个子类对象-构建子类,设置父类,从而实现对目标对象功能的扩展调用)https://www.cnblogs.com/qlqwjy/p/7550609.html
6. 线程状态与转换
- 初始(NEW ) 创建了线程,还未启动线程(未调用线程的start()方法)
- 运行(RUNNABLE) Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)
- 阻塞(BLOCKED) 表示线程阻塞于锁
- 等待(WAITING)进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)
- 超时等待(TIMED_WAITING)该状态不同于WAITING,它可以在指定的时间后自行返回
- 终止(TERMINATED)表示该线程已经执行完毕
- java线程的两种实现方式,a) 继承Thread类(继承Thread类之后就不能继承其他类了,启动线程需要new xxx.start()),b) 实现Runnable接口,此种方法可以访问同一个变量,c) 可以使用java.util.concurrent.Executors 线程池,Spring有ThreadPoolTaskExecutor
7. JVM相关
- 堆 堆存放的对象是线程共享的,所以多线程的时候需要同步机制。主要由新生代、老年代、永久代构成,1.8中移除整个永久代,取而代之的是一个叫元空间(Metaspace)的区域
- 栈 线程私有,栈描述的是Java方法执行的内存模型, 栈帧: 是用来存储数据和部分过程结果的数据结构。
- 方法区 用于存储已被虚拟机加载的类信息、常量、静态变量,如static修饰的变量加载类的时候就被加载到方法区中
- 本地方法栈 主要是保存native 的一些方法
- 程序计数器 程序计数器是一块很小的内存空间,它是线程私有的,可以认作为当前线程的行号指示器
8. Spring Boot(基于Spring,实现组件化配置java应用)
- 简化配置,自动装配,支持快速构建一个基于Spring框架的Java Application
- 使用 JavaConfiguration,用Java类替代XML的配置方式
- Spring Boot 对常用的第三方库提供了配置方案,可以很好的和Spring进行整合,一键式搭建功能完备的java企业级应用
- 优势,特点:
不需要任何XML配置文件
内嵌tomcat,可以直接部署
默认支持JSON数据,不需要转换
支持RESTful
配置文件非常简单,支持YAML格式
- Spring Boot2.x要求必须基于Spring5.x,Spring5.x Java版本需求jdk8
9.Spring Boot Starter 的工作原理
- Spring Boot在启动时有大概以下几个步骤:
a) Spring Boot在启动时会去依赖的starter包中寻找/resources/META-INF/spring.factories文件,然后根据文件中的配置的jar包去扫描项目依赖的jar包
b) 根据spring.factories 配置加载AutoConfigure类
c) 根据@Conditional 注解的条件,进行自动配置并将 Bean注入SpringContext
10. 分布式事务
- 事务补偿机制(定时任务补偿,消息补偿)
- 基于可靠消息的最终一致性(业务处理服务在业务事务提交之前, 向实时消息服务请求发送消息, 实时消息服务只记录消息数据, 而不是真正的发送。 业务处理服务在业务事务提交之后, 向实时消息服务确认发送。 只有在得到确认发送指令后, 实时消息服务才会真正发送)
- TCC事务补偿 (一个完整的业务活动由一个主业务服务于若干的从业务服务组成。 主业务服务负责发起并完成整个业务活动。 从业务服务提供TCC型业务操作。 业务活动管理器控制业务活动的一致性, 它登记业务活动的操作, 并在业务活动提交时确认所有的TCC型操作的Confirm操作, 在业务活动取消时调用所有TCC型操作的Cancel操作 )
11. Spring 、Spring Boot 和 Spring Cloud 的关系
- Spring 最初最核心的两大核心功能 Spring Ioc 和 Spring Aop 成就了 Spring,Spring 在这两大核心的功能上不断的发展,才有了 Spring 事务、Spring Mvc 等一系列伟大的产品,最终成就了 Spring 帝国,到了后期 Spring 几乎可以解决企业开发中的所有问题
- Spring Boot 是在强大的 Spring 帝国生态基础上面发展而来,发明 Spring Boot 不是为了取代 Spring ,是为了让人们更容易的使用 Spring 。
- Spring Cloud 是一系列框架的有序集合。它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 Spring Boot 的开发风格做到一键启动和部署。
- Spring Cloud 是为了解决微服务架构中服务治理而提供的一系列功能的开发框架,并且 Spring Cloud 是完全基于 Spring Boot 而开发,Spring Cloud 利用 Spring Boot 特性整合了开源行业中优秀的组件,整体对外提供了一套在微服务架构中服务治理的解决方案
12. Spring Boot2.x 新版本特性
- 响应式编程 Spring WebFlux/WebFlux.fn 响应式web编程,可用来构建异步的,非堵塞的,事件驱动的服务 来自Spring5.x
- HTTP/2 支持
- Kotlin 支持
- 全新的执行器架构
- 支持Quartz
- Security 大大简化类安全自动配置
- Metrics 引入Micrometer,来统一metrics的规范
- 监控方面有所增强,也主要来自Micrometer 监控服务各项指标自动监控
- 数据方面
db:默认引入HikariCP 链接池(一个高性能的JDBC连接池)
JOOQ的支持
Redis:默认引入了 Lettuce(使用netty NIO框架来高效的管理多个连接),替代了jedis作为底层连接redis
MongoDB\Hibernate优化
- Thymeleaf3 Spring Boot2.x支持Thymeleaf3
- OAuth2.0支持
- 组件更新
Jetty 9.4,Tomcat 8.5,Flyway 5,Hibernate 5.2,Gradle 3.4,Thymeleaf 3.0
13. java classloader
- 四种类加载器:a) 启动类加载器,b) 扩展类加载器,c) 系统类加载器,d) 自定义类加载器
a) 启动类加载器(根类加载器bootstrap class loader) 负责加载<JAVA_HOME>/lib路径下的核心类库或-Xbootclasspath参数指定的路径下的jar包. 出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类,启动类加载器无法被java程序直接引用
b) 扩展类加载器(extensions class loader)负责加载<JAVA_HOME>/lib/ext目录下或者由系统变量-Djava.ext.dir指定位路径中的类库,开发者可以直接使用扩展类加载器
c) 系统类加载器(应用类加载器 system class loader)在jvm启动时负责加载来自JAVA命令-classpath,java.class.path系统属性(也就是classpath路径)下的类库
d) 自定义类加载器(继承系统类加载器,实现用户自定义加载逻辑)重写findClass方法,通常web服务器都有自定义类加载器,如Tomcat(CommonClassLoader,CatalinaClassLoader,SharedClassLoader,WebappClassloader)没有遵守双亲委派机制,Spring类加载器(OverridingClassLoader默认先自己加载excludedPackages或excludedClasses,只有加载不到才会委托给双亲加载,DecoratingClassLoader内部维护了两个集合,如果你不想你的类被自定义的加载器管理,可以添加到这两个集合中)
- 类加载机制:全盘负责机制,双亲委派机制,缓存机制
全盘负责机制:是指一个类加载器负责加载某个Class时,该Class所依赖和引用其他Class也将由该类加载器负责载入
双亲委派机制:是指当加载某个Class时,先交由父类加载器视图加载该Class,只有父类加载器无法加载该类时,才尝试从自己的类路径中加载该类,此模式可以避免类的重复加载,也考虑了安全因素,保证java核心类不会被随意替换
缓存机制: 缓存机制将保证所有加载过的Class都会被缓存,当程序中需要某个Class时,类加载器先从缓存区中搜寻该Class,只有当缓存区中不存在该Class对象时,系统使用类加载器加载该类
14. mysql相关
- 存储引擎 MyISAM 和 Innodb,BerkeleyDB,Memory,Merge,Archive,CSV,MaxDB等十几个
MyISAM是非事务的存储引擎,适用于频繁查询的应用,表锁,不会出现死锁现象
Innodb 是支持事务,外键的存储引擎,行锁,适用于插入和更新操作比较多的应用。适合大数据,大并发
- SQL优化
选择合适的存储引擎
添加合适的索引,联合索引(索引的底层实现是基于B+树实现的,Innodb建议大部分表使用默认自增的主键作为主索引)
避免使用大字段,如text,longtext,尤其不能用做查询条件
避免使用全表扫描,避免使用在where中使用!=,null条件判断(会放弃使用索引而进行全表扫描),避免在where条件中使用 or,避免使用like%xxx%,避免使用in,not in 用exists替代,避免使用子查询(使用join),避免在where条件中使用函数(会使索引失效),避免使用select *查询所有字段,避免使用临时表(使用 union),避免使用游标,避免多表关联(3张以上的表考虑拆分业务,表关联时,小数据表在前)
- 数据库三范式
第一范式:属性的原子性约束,要求属性具有原子性,不可再分解;
第二范式:记录的 唯一性约束,要求记录有唯一性标识,即实体的唯一性;
第三范式:字段冗余性的约束,任何字段不能有其他字段派生出来,要求字段没有冗余;
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">