Java常见面试题
1.flag1和flag2的值是什么,为什么
Integer a=100;Integer b=100;boolean flag1 = a==b;
Integer a=130;Integer b=130;boolean flag2 = a==b;
结果:
flag1=true
flag2=false
考点:常量池
- 首先"=="是对比的对象地址
- 当 Integer a=100;Integer a=130; 这样赋值的时候会默认调用
valueOf()方法 - 查看源码后会发现当 -128<=x<127 时,直接从常量数据中取,是同一个对象所有相等,而这个范围外的是新建的对象所以不相等
// 赋值方法
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
// 默认值
static final int low = -128;
static final int high = h = 127;
static final Integer cache[]
// 常量数组
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
总结:
- 两个Integer值对比,-128~127时,是true,否则是false
- 两个int对比,使用"=="对比的是值
- 一个Integer与一个int对比,Integer会默认拆箱,对比的是数值不是地址了,所以会相等
- jvm对基础类型存储的是数值,对引用类型存储的是引用地址
- Integer对比可以转为int使用"==",或者直接使用equals
- Long和Short类型也做了相同的处理
2.ArrayList,LinkedList的区别,并说下他们的扩容机制
区别:
类型 | ArrayList | LinkedList |
---|---|---|
底层 | 数组 | 双向链表 |
内存 | 连续内存 | 无需连续内存 |
表尾插入 | 时间复杂度O(1) | 时间复杂度O(1) |
表头插入 | 时间复杂度为O(n) | 时间复杂度为O(1) |
表中插入 | 时间复杂度平均为O(n/2) | 时间复杂度平均为O(n/4),最慢的是中间O(n/2) |
删除 | 平均时间复杂度为O(n/2) | 平均时间复杂度为O(n/4),最慢的是中间O(n/2) |
修改 | 平均时间复杂度为O(1) | 平均时间复杂度为O(n/4),最慢的是中间O(n/2) |
查询 | 平均时间复杂度为O(1) | 平均时间复杂度为O(n/4),最慢的是中间O(n/2) |
线程安全 | 不安全 | 不安全 |
总结:
- ArrayList综合性能较高,建议多使用,适合情形:不须要频繁插入和删除数据到数组头部和前面部分,查询效率比LinkedList高
- 频繁增减头部适合LinkedList
扩容:
LinkedList大小不固定,无扩容
ArrayList扩容
- 默认10
- 扩容实在add时发生的,扩大到之前的1.5倍
- 旧数组移到新数组
- 扩容后的值与需要的值对比,使用较大的值
- 扩容后不能超过MAX_ARRAY_SIZE 2的31次方减1
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
3.阻塞队列的实现,ArrayBlockingQueue的底层实现
4.HashMap的get和put原理,在使用的时候怎么优化HashMap
5.JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计。
6.ThreadLocal的实现原理,有什么缺点?跟线程池结合使用要注意什么,怎么解决需要注意的这些问题
7.AQS实现公平锁和非公平锁的原理
8.说一说Fork/Join框架是什么
9.为什么等待和通知是在 Object 类而不是 Thread 中声明的
10.手写使用双重检查锁定在 Java 中创建线程安全的单例
11.如果你的Serializable类包含一个不可序列化的成员,会发生什么?你是如何解决的
12.CAS 实现的原理,是阻塞还是非阻塞方式?使用CAS有啥优缺点
13.原子操作类底层实现机制?自增操作是怎么保证原子性的
14.有三个线程 T1,T2,T3,怎么确保它们按顺序执行
15.如何在两个线程上共享数据?在两个进程上共享数据呢
16.一条 SQL 执行过长的时间,你如何优化,从哪些方面
17.MySQL 索引的原理
18.怎么设计分库分表,可以做到多维度查找
19.mysql索引在哪些情况下不起作用?
20.性别字段是否需要加索引,怎么优化这种类型的sql
21.mysql的存储引擎有哪些,分别有哪些区别
22.mysql悲观锁和乐观锁的区别,怎么实现
23.Mysql和redis数据一致性都有哪些方案,并说出每一种方案的优缺点
24.哨兵如何判断redis主从节点是否正常
25.怎么解决缓存雪崩、缓存穿透、缓存击穿
26.redis的持久化方式有哪些,推荐的是采用哪种,为什么
27.Redis的淘汰策略有哪些?具体的应用场景是啥
28.说一说Zookeeper的zab协议,工作中Zookeeper用在哪些业务场景下
29.说下Zookeeper的选举流程
30.分布式事务模型之XA和TCC的区别和联系
31.MQ集群宕机:怎么保证消息不丢失
32.简单说下spring的Ioc流程,它是如何解决循环依赖的问题,为什么这么解决
33.springmvc的核心是什么,请求的流程是怎么处理的
34.说下springboot的启动流程
35.Spring和Mybatis都使用了哪些设计模式,分别应用在哪些地方
36.mongodb和es有哪些异同点
37.new 一个对象的过程发生了什么(类加载、变量初始化、内存分配)
38.JVM 可能会抛出哪些 OOM
39.介绍JVM中7个区域,然后把每个区域可能造成内存的溢出的情况说明
40.CMS 和 G1 的垃圾回收步骤是?G1 相对于 CMS 的优缺点
41.内存泄漏时,如何实时跟踪内存变化情况,及如何定位问题代码
42.日常项目中,如果你接手,你准备从哪些方面调优
43.如何判断一个正整数是否存在于一个10亿个不重复正整数的集合中
44.(手写代码)假设有一个数组 A ,int[] A = { 1 , 3 , -1 ,0 , 2 , 1 , -4 , 2 , 0 ,1 … N}; 原来是需要查出大于 0 的数组,但是由于传参错误或者其他原因,导致查出 0 和负数了,现在要求在不使用新数组和新集合的情况下(即只使用这个 A 数组,因数组数据比较大,且只能用一次循环) 实现正数放到数组的前面,小于等于 0 的数放到数组的末尾
45.有一个单向链表,删除其中的偶数节点,并返回删除后的链表,用代码写下实现
例如: 输入:1->2->4->5->6 返回:1->4-> 6