工作笔记

强引用、弱引用、软引用和虚引用

强引用
强引用不会被垃圾回收器回收,内存不足时抛出OOM。
new创建对象时就是强引用,对象不使用时,将其设置为null,GC才会回收。
例如ArrayList中的clear()方法:

软引用
如果一个对象只具有软引用,则内存空间充足时,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。
当内存不足时,JVM首先将软引用中的对象引用置为null,然后通知垃圾回收器进行回收。

1
2
3
4
5
// 强引用
String strongReference = new String("abc");
// 软引用
String str = new String("abc");
SoftReference<String> softReference = new SoftReference<String>(str);

弱引用
在GC线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

1
2
3
4
5
6
// 强引用
String str = new String("abc");
// 弱引用
WeakReference<String> weakReference = new WeakReference<>(str);
// 弱引用转强引用
String strongReference = weakReference.get();


因为key是弱引用,当ThreadLocal对象除了Entry对象外没有其他引用的时候,在下次GC就直接回收了,但是value会随着线程生命周期存在,所以就发生了内存泄漏。
所以在ThreadLocal的源码中remove中调用expungeStaleEntry函数来解决这种情况:

虚引用

在任何时候都可能被垃圾回收器回收。 主要用来跟踪对象被垃圾回收器回收的活动。

虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

1
2
3
4
>String str = new String("abc");
>ReferenceQueue queue = new ReferenceQueue();
>// 创建虚引用,要求必须与一个引用队列关联
>PhantomReference pr = new PhantomReference(str, queue);

代码规范

命名规范

1、名副其实,见名知意
2、避免魔法值,使用全局常量、枚举

函数

1、一个函数只做一件事,保证短小
2、函数名由动词 / 动词+名词 构成
3、长而具有描述性的名称比短而令人费解的名称好
4、函数传参控制在一个或两个以内,多参数封装成对象
5、函数要么修改某对象的状态,要么返回该对象的信息

注释

注释是一种必须的恶,用来弥补我们使用代码表达意图时遭遇的失败,尽可能地少些注释,使用代码表达意图。

格式

1、函数、相关性不强的代码使用换行隔开
2、调用者应该放在被调用者上面

异常

不要返回 null 值,在新方法中抛出异常或是返回特例对象,比如空对象、空列表Collections.emptyList()等。
不要传递 null 值
将异常处理与主要逻辑隔离

单元测试
可读性
每个测试一个概念

单一权责原则
内聚,类中的每一个变量都被每一个方法使用,则该类具有最大的内聚性

匿名对象

在创建对象时,只通过new的动作在堆内存开辟空间,却没有把堆内存空间的地址值赋值给栈内存的某个变量用以存储,也就是创建对象后没有再操作对象。

匿名对象特点:

1、由于我们没有记录堆内存对象的地址值,所以只能用一次,再次使用就找不到了。

2、匿名对象的好处就是使用完毕就是垃圾,可以在垃圾回收器空闲时回收,节省内存空间。

创建对象后如果没有再对该对象进行别的操作就返回了,可以直接返回匿名对象无需再为匿名对象赋值。

1
2
3
4
5
6
7
8
9
/**
* public User getUser(){
* User user = new User();
* return user;
* }
**/
public User getUser(){
return new User();
}

类型转换抽象类

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
45
46
47
48
49
50
51
52
53
/**
* Description: 转换类基类
* @param <M> 待转对象类型
* @param <N> 预转对象类型
* @date 2021-2-20
*/
public abstract class AbstractConvertor<M, N> {
/**
* Description: 单个对象转换
* @param m 待转对象
* @return 转换后的对象
*/
public abstract N convert(M m);

/**
* Description: 单个对象反向转换
* @param n 待转对象
* @return 转换后的对象
*/
public abstract M reverseConvert(N n);

/**
* Description: 集合转换
* @param mList 待转对象集合
* @return 转换后的对象集合
*/
public List<N> convert(List<M> mList) {
List<N> nList = null;
if (mList != null) {
nList = new ArrayList<N>(mList.size());
for (M m : mList) {
nList.add(convert(m));
}
}
return nList;
}

/**
* Description: 集合转换
* @param mList 待转对象集合
* @return 转换后的对象集合
*/
public List<M> reverseConvert(List<N> nList) {
List<M> mList = null;
if (nList != null) {
mList = new ArrayList<M>(nList.size());
for (N n : nList) {
mList.add(reverseConvert(n));
}
}
return mList;
}
}

时间日期转换工具类

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
public class DateUtil {

private DateUtile(){}
/**
* 年月日时分秒格式的日期转化为字符串
* @param date
* @return
*/
public static String formatDateTime(Date date){
if(null == date){
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}

/**
* 年月日时分秒格式的字符串转化为日期
* @param str
* @return
*/
public static Date parseDateTime(String str){
if(null == str){
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = sdf.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}

/**
* 年月日格式的日期转化为字符串
* @param date
* @return
*/
public static String formatDate(Date date){
if(null == date){
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(date);
}

/**
* 年月日格式的字符串转化为日期
* @param str
* @return
*/
public static Date parseDate(String str){
if(null == str){
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sdf.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}

/**
* 时分秒格式的日期转化为字符串
* @param date
* @return
*/
public static String formatTime(Date date){
if(null == date){
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
return sdf.format(date);
}

/**
* 时分秒格式的字符串转化为日期
* @param str
* @return
*/
public static Date parseTime(String str){
if(null == str){
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
Date date = null;
try {
date = sdf.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}