随着互联网的环境变差,换工作也变的越来越难.生活也更加焦虑,因此开启了此文.以学习对抗焦虑.每天学习一点,可能是一道面试题也可能是算法,或者某些未知的领域,面试题主要复习开源项目JavaGuide,一个算法题,复习自代码随想录.

零.编程基础

  1. 学好英语,经常重构,尽可能做到代码就是注释,为自己的代码增加必要的测试.(当你做不到代码就是注释见面知意时,还是好好写好注释,为’屎山’留有一线生机),参考书籍《Clean Code》《重构》

一.Java基础

基本类型与包装类型,包装的缓存机制,自动拆箱装箱

基本类型与包装类型的区别

  • 用途:都可定义变量,包装类型更常用,还可用与泛型.
  • 存储方式:基本数据类型的局部变量存放在Java虚拟机栈中的局部变量表中,基本数据类型的成员变量(未被 static 修饰 )存放在 Java 虚拟机的堆中。包装类型属于对象类型,我们知道几乎所有对象实例都存在于堆中。
  • 占用空间:基本类型要小于包装类型(对象类型)
  • 默认空间:包装类型(对象)为null,基本类型有各自的默认值
  • 比较方式:基本类型使用==比较值,包装类型(对象)使用equals(),不可用==,对象比较的是内存地址
    1
    2
    3
    TODO
    为什么说是几乎所有对象实例都存在于堆中呢?
    这是因为 HotSpot 虚拟机引入了 JIT 优化之后,会对对象进行逃逸分析,如果发现某一个对象并没有逃逸到方法外部,那么就可能通过标量替换来实现栈上分配,而避免堆上分配内存

包装类型的缓存机制

Java基本类型的包装类型大部分都使用了缓存来提高性能.两种浮点数类型的包装类 Float,Double 并没有实现缓存机制。
Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False
Integer源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
*返回表示 Integer 指定 int 值的实例。如果不需要新 Integer 实例,则此方法通常应优先于构造函数 Integer(int)使用,因为此方法可能会通过缓存频繁请求的值来产生明显更好的空间和时间性能。此方法*将始终缓存 -128 到 127(含)范围内的值,并可能缓存此范围之外的其他值。
形参:
i – 一个 int 值。
返回值:
表示 Integer i的实例。
自:
1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

如果超出对应范围仍然会去创建新的对象,缓存的范围区间的大小只是在性能和资源之间的权衡.

1
2
3
4
// 如果需要-128-127 Integer对象,可以直接使用构造函数new对象
Integer i1 = new Integer(20);
// 直接赋值等于调用Integer.valueOf()方法,会使用缓存机制
Integer i2 = 20; // 等于 Integer i2 = Integer.valueOf(20);

自动装箱与拆箱

  • 装箱:基础->包装
  • 拆箱:包装->基础
    Integer为例:
  • 装箱使用了包装类的valueOf()方法,拆箱其实就是调用了 intValue()
    频繁拆装箱会严重影响系统性能

为什么浮点数运算的时候会有精度丢失的风险,如何解决

精度丢失

计算机报错数据都是以二进制0101进行保存的.并且在表示一个数字时,宽度是有限的,无限循环的小数被存储是只能被截断.导致的精度损失

如何解决

使用BigDecimal可以实现对浮点数的运算,不会造成精度丢失。通常情况下,大部分需要浮点数精确运算结果(比如涉及到钱的场景),都需要通过BigDecimal来做.

超过long整型的数字改怎么表示

超出基本类型的表达范围会有数值溢出的风险,64位的long整型是最大的整数类型为:9223372036854775807.
如果超过这个数值,可以使用BigInteger,BigInteger内部使用int[]数组来存储任意大小的整形数据.但是运行效率相对较低.

深拷贝与浅拷贝

  • 浅拷贝:浅拷贝会在堆上创建一个新的对象,如果原对象内部的属性是引用类型的话,浅拷贝会直接复制内部对象的引用地址,拷贝对象和原对象共用同一个内部对象.
  • 深拷贝:深拷贝会完全复制整个对象,包括这个对象所包含的内部对象

Object类的常见方法有哪些?

Object是所有类的父类,它一共提供了11个方法,其中多次出现native关键字

native关键字说明这个方法是原生函数(是使用C/C++语言实现的,并编译成了DLL,由Java去调用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
* native方法,用于返回当前运行时对象Class对象,使用了final关键字修饰(不允许子类重写)
*/
public final native Class<?> getClass();
/**
* native方法,用于返回对象的哈希码
*/
public native int hashCode();
/**
* 比较地址值是否相等,可被重写
*/
public boolean equals(Object obj);
/**
* native 方法,用于创建并返回当前对象的一份拷贝。
*/
protected native Object clone() throws CloneNotSupportedException;
/**
* 返回类的名字实例的哈希码的 16 进制的字符串。建议子类都重写这个方法。
*/
public String toString()
/**
* native 方法,唤醒等待的线程,如有多个则唤醒任意一个
*/
public final native void notify();
/**
* native 方法,唤醒所有等待线程
*/
public final native void notifyAll();
/**
* native 方法,暂停线程
*/
public final void wait() throws InterruptedException
/**
* native 方法,多了毫秒值设置
*/
public final native void wait(long timeoutMillis) throws InterruptedException;
/**
* 多了纳秒时间
*/
public final void wait(long timeoutMillis, int nanos) throws InterruptedException
/**
* 实例被垃圾回收器回收的时候触发的操作
*/
protected void finalize() throws Throwable

hashCode()有什么用

获取哈希码(int).哈希码的作用是确定该对象在哈希表中的索引位置.hashCode在Object中是native方法.哈希表是键值对(key-value)

JDK为什么要提供hashCode和equals两个方法去做对象是否相等

  1. hashCode效率更高
  2. hashCode使用的哈希算法,有可能会让多个不通的对象返回相同的哈希值.这时就需要使用equals方法去进行比较

为什么重写equals时必须重写hashCode

可能会导致,equals判断值相同,但是hashCode调用Object中的方法,两个对象哈希值不同,导致不相同

Java内存区域

字符串常量池的作用

Exception 和 Error 有什么区别

CheckedException与Unchecked Exception的区别

Throwable类常用方法

如何使用 try-with-resources 代替try-catch-finally

异常使用有哪些需要注意的地方

泛型的使用方式有哪几种

项目中哪里用到了泛型

反射的应用场景

注解的解析方法有哪几种

什么是序列号与反序列化

如果有些字段不想被序列化怎么处理

IO流为什么要分字节流与字符流

IO中的设计模式

BIO,NIO,AIO的区别

二.Mysql

基础语法

常用函数

练习题

索引

日志

事务处理

MVVC

SQL执行过程

查询缓存

自增主键一定是连续的吗

日期类型的选择建议

隐式转换造成索引失效

三.Redis

四.Spring

事务详解

2.Spring常见设计模式

3.自动装配

五.MyBatis

六.中间件

七.JVM