1、为什么重写equals还要重写hashcode?
两个方法均为判断两个对象是否相等,如果重写equals时,不重写hashcode,会导致某些场景下,例如将两个相等的自定义对象存储在set集合中,会出现程序异常的情况。
2、==和equals的区别
== | equals |
---|---|
速度快 | 速度慢 |
操作符 | 方法 |
比较基本类型时:对比对象的值;比较引用类型时:对比对象的引用地址 | 对比对象的值 |
3、为什么会出现4-3.6=0.400001
在二进制系统中无法精确的表示1/10
所以浮点数不适用于无法接受舍弃误差的金融计算中,应使用BigDecimal
类型
本质:
0.5能够表示,因为它可以表示成为1/2
0.75也能够表示,因为它可以表示成为1/2+1/(2^2)
0.875也能够表示,因为它可以表示成为1/2+1/(22)+1/(23)
0.9375也能够表示,因为它可以表示成为1/2+1/(22)+1/(23)+1/(2^4)
但是0.1不能够精确表示,因为它不能表示成为1/(2^n)的和的形式
4、finall作用
- 修饰引用
- 基本类型:标记该引用为产量
- 引用类型:对象本身可修改,指向对象的引用不可修改
- 方法:可被继承,不可重写
- 类:无法继承
5、Java的集合类
- List
- ArrayList,基于数组
- LinkList,基于链表
- set
- HashSet,基于哈希表
- LinkHashSet,基于链表
- TreeSet,基于树
- map
- HashMap,基于哈希表
- LinkHashMap,基于数组
- TreeMap,基于哈希表
6、ArrayList和LinkLsit的区别
ArrayList基于数组,对随机index的访问比较快,空间浪费体现在列表结尾的预留空间
LinkList基于链表,增加和删除元素比较快,空间浪费体现在每个元素都需要消耗一定的空间
7、Java8新特性
- Lambda表达式和函数式编程
- 接口的默认方法和静态方法
- 方法引用
- 重复注解
- …
8、HashMap在jdk1.7和jdk1.8的区别
- 底层结构:1.7采用数组+链表,1.8采用数组+链表+红黑树
- 初始化方式:哈希表为空时,1.7采用inflateTable()初始化一个数组;1.8采用resize()扩容
- put()实现方式:1.7采用头插法;1.8采用尾插法
- hash()实现方式:1.7直接计算key的hashCode值;1.8采用key的hashCode异或key的hashCode进行无符号右移16位的结果
9、什么是死锁?死锁的产生条件?
两个或两个以上的进程在执行过程中,由于竞争资源或相互通信造成的一种阻塞的现象。
- 互斥条件:一段时间内某资源被占用,其他进程想要调用就只能等待(相互竞争)
- 请求与保持条件:进程保持至少一个资源,且希望请求新的资源,但该资源被占用,此时请求进程被阻塞,但对自己获得的资源保持不放(吃着碗里的,看着锅里的)
- 不可剥夺条件:进程获得的资源未使用完毕之前,不可被其他进程强行夺走,只能由其主动释放
- 循环等待条件:若干进程形成首位相接等待资源的关系
10、线程有几种状态?
- 新建:新创建的线程对象
- 可运行:创建后,该线程的start()方法被调用,进入线程池,等待线程调度选中
- 运行:线程获得了cpu的时间片,执行程序代码
- 阻塞:由于某些原因放弃了cpu使用权,暂时停止运行
- 无限期等待:线程进入等待状态,表示当前线程需要等待其他线程做出一些特定动作(通知或中断)
- 限期等待:超时等待状态,会在指定的时间内自行返回
- 死亡:main方法执行结束,不可复生
11、哪些进程调度算法?
- 先来先服务
- 时间片轮转
- 短作业优先:运行时间最短
- 最短剩余时间优先:象笔短作业优先增加抢占机制,优先选取剩余时间最短的进程
- 高响应度优先:通过等待时间和运行时间计算响应比
- 优先级调度:根据优先级选取
12、什么是缓冲区溢出?
计算机向缓冲区填写数据时超出了缓冲区本身的容量,溢出的数据覆盖在合法的数据上。
危害:
- 程序奔溃,导致拒绝服务
- 跳转并执行一段恶意代码
原因:程序中没有仔细检查用户的输入
13、计算机网络各层有什么协议
- 应用层:DHCP、FTP、HTTP、SMTP、RPC
- 传输层:TCP/UDP 数据单元:数据段
- 网络层:IP、ARP 数据单元:数据包
- 数据链路层:PPP、ARQ 数据单元:帧
- 物理层:数据单元:比特
14、TCP和UDP的区别
TCP | UDP |
---|---|
面向有连接 | 面向无连接 |
可靠的 | 不可靠的 |
基于字节流 | 基于报文 |
点对点 | 一对一、一对多、多对一、多对多 |
工作效率低 | 工作效率高,适用于高速传输或广播通信 |
资源要求多 | 资源要求低 |
15、三次握手和四次挥手的目的
保持连接时双工的,防止A端已经失效的连接请求突然又传到B端,被误以为是A端再次发出的请求
16、HTTP协议和HTTPS协议的区别?
HTTP明文传输,数据未加密,安全性较差
HTTPS(SSL+HTTP)数据传输加密,安全性较好
17、MySQL索引的最左原则
在联合索引中,如果你的SQL语句用到了联合索引中的最左边的索引,那么这条SQL语句就可以利用这个联合索引进行匹配
例如:某表现有索引(a,b,c)
select * from t where a=1 and b=1; #这样可以利用到定义的索引(a,b,c),用上a,b
select * from t where a=1 and b=1; #这样可以利用到定义的索引(a,b,c),用上a,b
select * from t where a=1 and c=1; #这样可以利用到定义的索引(a,b,c),但只用上a索引,b,c索引用不到
18、MySQL存储引擎中,MylSAM和InnoDB的区别
InnoDB | MyISAM |
---|---|
支持事务 | 不支持事务 |
支持外键 | 不支持外键 |
聚集索引 | 非聚集索引 |
支持行锁、表锁 | 支持表锁 |
必须有主键 | 可以没有 |
不保存表的行数 | 保存了表的行数 |
19、优化数据库性能的方法
数据库设计:
- 选取何使的字段属性(VARCHAR、CHAR)
- 数据库索引
SQL语句优化:
- 避免使用子查询,使用JOIN连接查询代替
- 能使用UNION ALL就不要用UNION、UNION会自动压缩集合的重复结果
- 皮面使用!=或<>操作符,使用该操作符会不使用索引
- 对OR子句的优化,如使用UNION ALL代替OR
- IN或NOT IN的优化
- BETWEEN AND替换IN
- EXISTS替换IN
- LEFT JOIN替换IN
- IS NULL或IS NOT NULL优化,因为它会放弃使用索引
- LIKE优化
- 避免SQL语句中的表达式计算
- LIMIT分页优化
- …
20、如何定位慢查询
- 使用慢查询日志
- 使用explain等工具分析sql
- show processlist查看正在执行的慢查询
21、MySQL支持行锁还是表锁?分别有什么优缺点
MySQL常用的引擎是InnoDB,支持行锁和表锁
多个事务操作同一行数据时,后来的事务处于阻塞状态,后来的事务可以操作其他的行数据,解决了表锁高并发性能低的问题。
行锁的优点:锁的粒度小,发生锁冲突的概率低;处理并发的能力强
行锁的缺点:开销大;加锁慢;会出现死锁
22、Spring的IOC和AOP是什么?有哪些优点?
IOC(DI)控制反转,一种通过描述(XML或注解)并通过第三方生产或获得特定对象的方式。
AOP面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
- 降低组件之间的耦合度,实现解耦
- 可以提供众多服务,如事务管理,消息服务等
- 容器提供了单例模式
- 可以使用AOP实现全线拦截,运行期监控等功能
- 低侵入设计,代码污染极低
23、Spring使用到了哪些设计模式?
- 工厂模式(IOC,通过工厂模式创建bean对象)
- 单例模式(Bean默认都是单例的,唯一的线程池、缓存、对话框等)
- 代理设计模式(AOP实现)
- 模板方法(jdbcTemplate、hibernateTemplate等模板类的实现)
- 观察者模式(监听器,驱动模型)
- 适配器模式(AOP中的Advice增强或通知)
- 包装器模式(项目连接多个数据库,可以通过切换数据源访问不同的数据库)
24、Spring Bean的生命周期
其中第3、4步为初始化前执行,5~6步为初始化操作,第7步在初始化后执行
- 实例化
- 属性赋值
- 设置相关属性和依赖
- 初始化
- Aware接口的依赖注入
- BeanPostProcessor的前置处理
- InitializingBean(初始化bean)处理
- init-method处理
- BeanPostProcessor的后置处理
- 销毁
- 注册销毁相关的回调接口
- DisposableBean 处理
- destory-method处理
25、MyBatis如何实现延迟加载
延迟加载:在真正的使用数据时才发起查询,不用的时候不用查,按需查询(懒加载)
延迟加载参数配置:
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
一对一的查询:
<association property="user" column="uid" javaType="com.mybatis.domain.User" select="com.mybatis.dao.IUserDao.findById"></association>
一对多的查询:
<collection property="accounts" ofType="com.mybatis.domain.Account" select="com.mybatis.dao.IAccountDao.findAccountByUid" column="id"></collection>
26、MyBatis的多级缓存机制
- 一级缓存:基于SqlSession,也叫本地缓存,第一次查询数据库会写在缓存中,第二次查询直接在缓存中读取,两次查询语句之间发生了增删改的操作,会清空该缓存(默认开启)
- 二级缓存:基于namespace,如果两个mapper的namespace相同,则共用一个二级缓存(默认不开启)
Git
27、如何解决提交冲突
产生原因:在合并分支时,master分支和dev分支恰好有人修改了同一个文件,git不知道以那一个人的文件为准
解决方法:IDE会对比本地文件和远程分支的文件,然后将远程分支的文件手动修改到本地,然后再提交冲突的文件,使其保证与远程分支的文件一致
28、提交的时候不小心出现误操作,如何撤销
已经commit,没有push
#会退到上一个版本
git reset --hard HEAD^
三个参数:
- soft提交:将HEAD引用指向指定提交
- mixed提交:将HEAD指向指定提交
- hard提交:将HEAD指向给定提交
commit之后,并且push到了云端
# 撤销最近的一次提交
git revert HEAD --no-edit
29、什么是Git Flow,它有什么好处?
Git Flow是一种代码开发合并管理流程的思维模式或者是管理方法。是大家一起开发的一种软约定
优点:
- 适应场景多
- 不影响开发进度
- 分支使用相对有条理
- 保证线上版本稳定
缺点:
- 因为分支态度,可能出现git log混乱的局面
- 同时维护master和dev两个分支有时是没有必要的
美团
30、Java线程池核心参数与工作流程,拒绝策略
线程池参数:
线程池的执行流程:
- 当线程数小于核心线程数时,使用核心线程数
- 当核心线程数用完,且任务队列未满,则将多余的线程放入任务队列(阻塞队列)中
- 当任务队列(阻塞队列)满的时候,就启动最大线程数
- 当最大线程数页达到时,启动拒绝策略
拒绝策略:
- AbortPolicy,默认的拒绝策略,即丢弃任务并抛出RejectedExecutionException异常信息
- DiscardPolicy,丢弃任务,但是不抛出异常
- DiscardOldestPolicy,丢弃队列中最前面的任务,然后重新提交被拒绝的任务(丢弃队列中的任务时,不会抛出异常)
- CallerRunsPolicy,由调用线程处理该任务(不会丢弃任务,最后所有任务都完成了,不会抛出异常)
31、Synchronized和Lock的原理和区别
可重入锁:当线程获取某个锁后,还可以继续获取它,可以递归调用,而不会发生死锁
不可重入锁:与可重入相反,获取锁之后不能重复获取,否则会死锁
非公平的锁:获取锁的时候,并不是根据所申请的时间先后给等待的线程分配锁
相同点:
- 都是可重入锁
- 保证了可见性和互斥性
- 都可以用于控制多线程对共享对象的访问
不同点:
- ReentrantLock等待可中断(等待锁的释放)
- Synchronized是Java中的关键字是JVM级别的锁,而ReentrantLock是一个Lock接口下的实现类,是API层面的锁
- Synchronized中的锁是非公平的,ReentrantLock默认是非公平的,但可以通过修改参数实现公平锁
- Synchronized隐式获取锁和释放锁,ReentrantLock显式获取锁和释放锁,需要再finally控制块中释放锁,否则会造成死锁
32、重写和重载的区别
重写发生在子类继承父类时,对父类的方法进行的改写操作
重载是发生在一个类中,相同的函数名,但是有不同的参数,参数的个数不一样,参数的位置不一样,参数的类型不同,这就是重载,常见的有构造函数,有参构造和无参构造。
33、线程的状态及转移
- 新建:新创建的线程对象
- 可运行:创建后,该线程的start()方法被调用,进入线程池,等待线程调度选中
- 运行:线程获得了cpu的时间片,执行程序代码
- 阻塞:由于某些原因放弃了cpu使用权,暂时停止运行
- 无限期等待:线程进入等待状态,表示当前线程需要等待其他线程做出一些特定动作(通知或中断)
- 限期等待:超时等待状态,会在指定的时间内自行返回
- 死亡:main方法执行结束,不可复生
阻塞和等待的区别:
- 阻塞状态是进入一个排他锁,进入阻塞状态是被动的
- 等待状态是在等待一段时间或等待一个唤醒动作,进入等待状态时主动的
34、Synchronized原理
原理:每一个对象都有一个Monitor(监听器)与之对应,当Monitor被持有之后,它将处于锁定状态。Monitor对象存在于每个Java对象的对象头Mark Word中(存储的指针的指向),这也是为什么Java中任何对象都可以作为锁的原因
- 作用于成员变量和非静态方法时,锁住的是对象的实例,即this对象
- 作用域静态方法是,锁住的是Class实例
- 作用于代码块时,锁住的时代码块中配置的对象
35、JVM垃圾回收器
追问1:CMS垃圾回收器的过程是什么样的?会带来什么问题?
追问2:G1垃圾回收器的改进是什么?相比于CMS突出的地方是什么?
追问3:现在jdk默认使用的是哪种垃圾回收器?
36、HashMap在jdk1.7和jdk1.8的区别
HashMap
- 底层结构:1.7采用数组+链表,1.8采用数组+链表+红黑树
- 初始化方式:哈希表为空时,1.7采用inflateTable()初始化一个数组;1.8采用resize()扩容
- put()实现方式:1.7采用头插法;1.8采用尾插法
- hash()实现方式:1.7直接计算key的hashCode值;1.8采用key的hashCode异或key的hashCode进行无符号右移16位的结果
ConcurrentHashMap
- 在jdk1.7中采用数组+链表,在jdk1.8中采用数组+链表+红黑树
- 在1.7中采用分段锁segment实现线程安全,在1.8中采用synchronized 和CAS来实现
37、CAS操作原理与实现
38、TCP和UDP区别
TCP | UDP |
---|---|
面向有连接 | 面向无连接 |
可靠的 | 不可靠的 |
基于字节流 | 基于报文 |
点对点 | 一对一、一对多、多对一、多对多 |
工作效率低 | 工作效率高,适用于高速传输或广播通信 |
资源要求多(首部开销20字节) | 资源要求低(首部开销8字节) |
追问:TCP和UDP的使用场景?
某些情况下UDP是一种最有效的工作方式(一般用于即时通讯),比如QQ语音、QQ视频,直播等等。
TCP一般用于文件传输、发送和接收邮件、远程登录等场景。
追问:TCP是如何保证可靠传输的?
- 应用数据被分割成认为最合适发送的数据块
- TCP将每个包编号,有序发给应用层
- 检验和:TCP将保持它首部和数据的检验和,以确保数据在传输过程中的一致。
- 流量控制:TCP连接的每一方都有固定大小的缓冲空间,接收端只允许发送端发送能够接纳的数据。
- 拥塞控制:当网络拥塞时,减少数据的发送。
- ARQ协议:每发完一个分组就停止发送,等待对方确认再法下一个。
- 超时重传:TCP发出一个段时,会启动一个定时器,等待对方确认。如果不能及时收到确认,将重发该报文段。
- TCP接收端会丢弃重复的数据。
HashMap和Hashtable的区别
HashMap可以存放null
HashTable不能存放null
HashMap不是线程安全的类
HashTable是线程安全的类
StringBuffer和StringBuilder的区别
StringBuffer 是线程安全的
StringBuilder 是非线程安全的
ArrayList和Vector的区别
Vector是线程安全的类,而ArrayList是非线程安全的。