强引用、弱引用、软引用和虚引用
强引用
强引用不会被垃圾回收器回收,内存不足时抛出OOM。new
创建对象时就是强引用,对象不使用时,将其设置为null
,GC才会回收。
例如ArrayList
中的clear()
方法:
软引用
如果一个对象只具有软引用,则内存空间充足时,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。
当内存不足时,JVM
首先将软引用中的对象引用置为null
,然后通知垃圾回收器进行回收。
1 | // 强引用 |
弱引用
在GC线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
1 | // 强引用 |
因为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 | /** |
类型转换抽象类
1 | /** |
时间日期转换工具类
1 | public class DateUtil { |