这篇文章用来记录本人遇到的真实面试题,并会给出个人认为相对正确的答案,由于是面试专题,讲究现场发挥,所以不尽量保持答案言简意赅的原则,不求甚解,如果要深入学习知识点,请移步其他文章。
理论篇
1. springboot中bean是怎样加载的
2. 怎样快速排查linux中的端口占用
以查找8080端口为例,有以下几种方法
> netstat -tunlp | grep 8080 或 netstat -tnlp | grep 8080
> lsof -i:8080
> fuser 8080/tcp
3. 聊聊HashMap(基础问题必问)
这里有的讲,省略一顿扒拉,关键点:hashMap的数组+链表结构,put()的过程,hash碰撞,初始容量默认16,扩容阈值默认0.75,如何扩容(大概就是新建一个容量翻倍的HashMap,原来的数据重新计算hashCode放入新的Map中),扩容会消耗性能,为了防止频繁扩容创建HashMap时应该合理的制定初始容量,大小最好为2的整数次幂。
4. 谈谈对IOC的理解,有什么好处
IOC即控制反转,就是Spring帮我们管理我们需要的资源,在容器启动时就为我们创建好需要的对象,在我们需要使用某个对象时,无需手动创建,而是通过依赖注入引入。这样带来的好处很多,对象的提前创建和集中管理方便了对象的复用,减少了频繁创建对象所造成的性能损耗,同时实现组件之间的解耦,提高程序的灵活性和可维护性。
IOC实现的原理:反射
5. Object类有哪些方法
1.clone()
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。
2.getClass()
final方法,获得运行时类型。
3.toString()
该方法用得比较多,一般子类都有覆盖。
4.finalize()
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
5.equals()
该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。
6.hashCode()
该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
一般必须满足obj1.equals(obj2)==true。可以推出obj1.hashCode()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。
7.wait()
8.notify()
9.notifyAll()
6. 有一个表,其中有一列是数字类型,怎么得到第二大的数,写sql
假设表为TABLE,数字字段列名为N
SELECT N
FROM (SELECT N, ROWNUM
FROM (SELECT N, ROWNUM FROM TABLE ORDER BY N)
WHERE ROWNUM < 3 ) T
WHERE T.ROWNUM = 1;
我写完后面试官又问能不能不用ROWNUM来实现,我不知道他问这个是什么用意,才疏学浅,如果还有其他办法希望能在评论区讨论。
7. mybatis的二级缓存怎么实现,作用范围
实现:二级缓存默认关闭,先在mybatis-conf.xml中开启二级缓存
,然后在mapper.xml文件中添加标签
,再为需要缓存的查询方法中加入useCache="true"
开启缓存
一级缓存的作用范围是sqlSession,会话结束,sqlSession关闭,缓存清空。
二级缓存的作用范围是Mapper
8. 聊聊JVM
9. JVM内存中那些内存是线程独享的
虚拟机栈,本地方法栈,程序计数器
10. ThreadLocal的是怎么实现的
10. 有线上JVM调优经历吗,讲下经过
这里也是一顿扒拉
11. AOP怎么实现
12. 普通视图和物化视图的区别
普通视图并不是实际的表,相当于一段sql,它的作用是减少将sql与代码解耦,在代码层面使用视图就相当于直接面对一张可视的表。减少代码逻辑的复杂性,但是并不能带来性能的提升。
物化视图是是一张实际的表,同样它是基于其他基础表数据关联形成的一张数据表,它有三种刷新方式on [commit|demand] | start with (start_time) next (next_time)]
,分别是发生事务提交时刷新,手动刷新,和指定时间刷新,默认是手动刷新。
13. sql中什么行为会不走索引
- where条件中使用or
- where条件中使用not in
- like的模糊查询左边使用%
原因:最左匹配原则
b+ 树的数据项是复合的数据结构,比如 (name,age,sex) 的时候,b+ 树是按照从左到右的顺序来建立搜索树的,比如当 (张三,20,F) 这样的数据来检索的时候,b+ 树会优先比较 name 来确定下一步的所搜方向,如果 name 相同再依次比较 age 和 sex,最后得到检索的数据;但当 (20,F) 这样的没有 name 的数据来的时候,b+ 树就不知道第一步该查哪个节点,因为建立搜索树的时候 name 就是第一个比较因子,必须要先根据 name 来搜索才能知道下一步去哪里查询
比如当 (张三, F) 这样的数据来检索时,b+ 树可以用 name 来指定搜索方向,但下一个字段 age 的缺失,所以只能把名字等于张三的数据都找到,然后再匹配性别是 F 的数据了, 这个是非常重要的性质,即索引的最左匹配特性。(这种情况无法用到联合索引)
14. where 和 having 的区别
1.用的地方不一样
where可以用于select、update、delete和insert into values(select * from table where ..)语句中。
having只能用于select语句中
2.执行的顺序不一样
where的搜索条件是在执行语句进行分组之前应用
having的搜索条件是在分组条件后执行的
即如果where和having一起用时,where会先执行,having后执行
3.子句有区别
where子句中的条件表达式having都可以跟,而having子句中的有些表达式where不可以跟;having子句可以用集合函数(sum、count、avg、max和min),而where子句不可以。
笔试篇
1. 实现一个单例模式
public class Single {
private volatile static Single INSTANCE;
private Single() {};
public static Single getInstance() {
if (INSTANCE == null) {
sychronized (Single.class) {
if (INSTANCE == null) {
INSTANCE = new Single();
}
}
}
return INSTANCE;
}
}
2. 实现一个工厂模式
实现原则,一个工厂接口,多个不同实现
假设要设计一个生产各种口味巧克力的工厂
先定义一个接口,这个接口定义了生产巧克力的方法,相当于制造巧克力的机器
public interface Machine {
public String makeChocolate();
}
需要三台机器,实现Machine接口,用来制作巧克力
// 机器1
public class RedMachine implements Machine {
public String makeChocolate () {
return "红色巧克力";
}
}
// 机器2
public class BlackMachine implements Machine {
public String makeChocolate () {
return "黑色巧克力";
}
}
// 机器3
public class WhiteMachine implements Machine {
public String makeChocolate (){
return "白色巧克力";
}
}
然后创建一个工厂,定义一个制造机器的方法,你可以实现这个接口得到你想要的机器
public interface Factory {
public Machine getMachine();
}
实现工厂接口,得到想要的机器
public class RedChocolateFactory implements Factory {
public Machine getMachine() {
return new RedMachine();
}
}
public class BlackChocolateFactory implements Factory {
public Machine getMachine() {
return new BlackMachine();
}
}
public class WhiteChocolateFactory implements Factory {
public Machine getMachine() {
return new WhiteMachine();
}
}
如此工厂模式就实现完了,下面是客户端
public class Client {
public static void main(String[] args) {
Factory redChocolateFactory = new RedChocolateFactory();
System.out.plintln(redChocolateFactory.getMachine().makeChocolate());
Factory blackChocolateFactory = new BlackChocolateFactory();
System.out.plintln(blackChocolateFactory.getMachine().makeChocolate());
Factory whiteChocolateFactory = new WhiteChocolateFactory();
System.out.plintln(whiteChocolateFactory.getMachine().makeChocolate());
}
}
3. 实现一个斐波那契数列,最后一个数是前面一个数之和,长度可以自定义控制,例如0,1,2,3,5,8,13,21,34
public class Fibonacci {
public List getList(int size) {
List list = new ArrayList<>();
list.add(0);
list.add(1);
for (int i = 0; i < size - 2; i++) {
int length = list.size();
list.add(list.get(length - 1) + list.get(length - 2));
}
return list;
}
public static void main(String[] args) {
Fibonacci fibonacci = new Fibonacci();
System.out.println(fibonacci.getList(10));
}
}