面试总结
java在什么情况下会使用static关键字
1.静态变量可以被所有的类的实例所共享
2.当一个方法和变量需要被初始化加载时,或者被经常调用的时候可以使用static,用static修饰的方法或者变量可以直接类名调用,反之需要实例化一个对象才可以调用
3.声明一个static块,仅在类被加载时执行一次
java在什么情况下会使用抽象类或者接口
抽象类:把共有的属性方法抽象出来,统一写在一个地方,这样父类中添加方法时,子类中便全部都拥有了,方便维护,体现了代码的复用性
接口:抽象的是行为 - 同一种行为的不同实现方式,当多个对象都拥有相同的行为,但是行为的具体实现方式不一样的时候可以用接口抽象
面向对象
抽象: 抽象是将一类对象的共同特征总结出来构造类的过程, 包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属
继承是从已有类得到继承信息创建新类的过程.提供继承信息的类被称为父类(超类、基类) ;得到继承信息的类被称
多态:在Java中有两种形式可以实现多态:继承(多个子类对同-方法的重写)和接口(实现接口并覆盖接口中同-方法)。
为什么要有hashcode
当你把对象加入HashSet时,HashSet 会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他已经加入的对象的hashcode 值作比较,如果没有相符的hashcode, HashSet会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用equals()方法来检查hashcode相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。
Hashmap
JDK7中的HashMap,是基于数组+链表来实现的,它的底层维护一个Entry数组。它会根据计算的
hashCode将对应的KV键值对存储到该数组中,一旦发生hashCode冲突,那么就会将该KV键值对放到
对应的已有元素的后面, 此时便形成了一个链表式的存储结构。
JDK7中HashMap的实现方案有一个明显的缺点,即当Hash冲突严重时,在桶上形成的链表会变得越来
越长,这样在查询时的效率就会越来越低,其时间复杂度为O(N)。
JDK8中的HashMap,是基于数组+链表+红黑树来实现的,它的底层维护一个Node数组。当链表的存
储的数据个数大于等于8的时候,不再采用链表存储,而采用了红黑树存储结构。这么做主要是在查询
的时间复杂度上进行优化,链表为O(N),而红黑树一直是O(logN),可以大大的提高查找性能
如何得到一个线程安全的Map?
参考答案
\1. 使用Collections工具类,将线程不安全的Map包装成线程安全的Map;
\2. 使用java.util.concurrent包下的Map,如ConcurrentHashMap;
\3. 不建议使用Hashtable,虽然Hashtable是线程安全的,但是性能较差。
启动线程的方式
继承Thread类
实现Runable接口
实现Callable接口
使用线程池,使用Executors
可缓存线程池/定长线程池/单线程化的线程池/具有抢占式操作的线程池
什么情况下重写equals和hashcode
比较两个实例是否相等时会重写equals
自定义类型作为HashMap的key:重写hashcode
java中短整型是2个字节
线程池
线程池是统一管理和维护线程的地方,可以节省资源的消耗
频繁的开启和关闭线程会导致CPU上下文的切换,消耗资源
springboot常用注解
@Configuration、@EnableAutoConfiguration、@ComponentScan
@Repository、 @Service 、@RestController
@SpringBootApplication
内部类
静态内部类
是定义在内部的静态类,可以访问外部所有静态变量,不可以访问非静态变量
创建方式: new 外部类.静态内部类()
成员内部类
定义在内部,成员位置上的非静态类,可以访问外部的所有的变量或者方法
创建方式:外部实例.new 内部类()
局部内部类
定义在方法中的内部,定义在方法中的局部类可以访问外部类中的所有方法,定义在静态方法中局部类可以访问外部类的静态方法和变量
创建方法:new 内部类()
匿名内部类
没有名字的内部类,必须先继承或实现一个已有的接口,不能定义任何静态成员或者方法
创建方式:new 接口/类{
//内部实现
}
内部类的优点
具有很好的封装性
有效的实现了多继承
方便函数回调
IO流
输入流/输出流
字节流/字符流
节点流/处理流
输入流是将数据从硬盘/输入设备读取到内存
数据库
第一范式(1NF):每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项
第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖,表中的每个数据都是唯一的
第三范式(3NF):在2NF基础上消除传递依赖
所有的字段都适合创建索引吗
不是
频繁的更新字段的表不宜加索引
数据较少的表不宜加索引
where查询语句中用不到的字段不宜加索引
参与计算的列不宜加索引
数据重复的字段不宜加索引
数据库索引失效了怎么办
怎么避免失效
使用组合索引时,尽量遵循最左前缀原则
不在索引上做任何操作,如,计算,求和
少用select * 查询语句,减少回表,多使用子查询
少用like,模糊查询,or语句
少使用!=
索引是越多越好吗
索引也占用磁盘空间,影响性能
如何评估一个索引创建的是否合理
数据少的表不要加索引
频繁更新的表不要加索引
但一个字段是唯一的时候可以加索引
频繁使用排序,分组操作的时候,使用索引会加快速率
死锁产生的条件
互斥
占用且申请
不可抢占
循环等待
数据库的优化
针对查询:使用索引
针对慢查询:慢查询日志分析
插入:禁用索引
数据库表结构:我们可以通过将字段很多的表拆分成多张表、增加中间表、增加冗余字段等方式进行优化
UML图是统一建模语言
泛化:是一种继承关系,表示一般与特殊的关系,它指定了子类如何特化父类的所有特征和行为。 带三角箭头的实线,箭头指向父类
实现:是一种类与接口的关系,表示类是接口所有特征和行为的实现. 带三角箭头的虚线,箭头指向接口
关联:是一种拥有的关系,它使一个类知道另一个类的属性和方法;如:老师与学生,丈夫与妻子关联可以是双向的,也可以是单向的。双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头
聚合:是整体与部分的关系,且部分可以离开整体而单独存在。如车和轮胎是整体和部分的关系,轮胎离开车仍然可以存在。 带空心菱形的实心线,菱形指向整体
组合:是整体与部分的关系,但部分不能离开整体而单独存在。如公司和部门是整体和部分的关系,没有公司就不存在部门 带实心菱形的实线,菱形指向整体
依赖:是一种使用的关系,即一个类的实现需要另一个类的协助,所以要尽量不使用双向的互相依 带箭头的虚线,指向被使用者
时序图
角色,对象,生命线,消息,
说一说你对数据库优化的理解
针对查询,我们可以通过使用索引、使用连接代替子查询的方式来提高查询速度。
针对慢查询,我们可以通过分析慢查询日志,来发现引起慢查询的原因,从而有针对性的进行优化。
针对插入,我们可以通过禁用索引、禁用检查等方式来提高插入速度,在插入之后再启用索引和检查。
针对数据库结构,我们可以通过将字段很多的表拆分成多张表、增加中间表、增加冗余字段等方式进行优化
该如何优化MySQL的查询
使用索引:优化子查询:
怎样插入数据才能更高效
禁用索引 禁用唯一性检查 使用批量插入 禁用自动提交
表中包含几千万条数据该怎么办?
优化SQL和索引
增加缓存,如memcached、redis
读写分离,可以采用主从复制,也可以采用主主复制
MySQL的慢查询优化有了解吗?
开启慢查询日志 分析慢查询日志
Spring
Spring是一个轻量级的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。
Spring Core Spring Context
spring属于低侵入式设计,代码的污染极低/减低组件的耦合性/Spring提供了AOP技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用/spring对于主流的应用框架提供了集成支持
AOP:用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理
IOC:就是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部资源
IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的
实例化,初始init,接收请求service,销毁destroy;
Maven的生命周期
maven有三套生命周期,分别为:
1、clean 周期:主要用于清理上一次构建产生的文件,可以理解为删除target目录
2、默认周期,
主要阶段包含:
1)process-resources 默认处理src/test/resources/下的文件,将其输出到测试的classpath目录中,
2)compile 编译src/main/java下的java文件,产生对应的class,
3)process-test-resources 默认处理src/test/resources/下的文件,将其输出到测试的classpath目录中,
4)test-compile 编译src/test/java下的java文件,产生对应的class,
5)test 运行测试用例,
6)package 打包构件,即生成对应的jar, war等,
7)install将构件部署到本地仓库,
8)deploy 部署构件到远程仓库
常用的 JVM 调优的参数都有哪些?
• -Xms2g:初始化推大小为 2g;
• -Xmx2g:堆最大内存为 2g;
• -XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;
• -XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;
• –XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
• -XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
• -XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
• -XX:+PrintGC:开启打印 gc 信息;
• -XX:+PrintGCDetails:打印 gc 详细信息。
jconsole:用于对 JVM 中的内存、线程和类等进行监控;
• jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等
四种隔离级别
读未提交
这种事务隔离级别下,select语句不加锁。此时,可能读取到不一致的数据,即“读脏 ”。这是并发最高,一致性最差的隔离级别。
读已提交,
在互联网大数据量,高并发量的场景下,几乎不会使用,上述两种隔离级别。
可避免脏读的发生。
可重复读
可避免脏读、,不可重复读的发生。
串行行
不可重复读的发生。