Java四种引用包括强引用,软引用,弱引用,虚引用。
先上引用的两个实体类
/**
* 实体列A
*/
static class People{
String name="A";
int age=12;
String sex="男";
}
/**
* 实体列B
*/
static class Student{
String name="B";
int age=12;
String sex="男";
}
强引用(StrongReference)
强引用,顾名思义,作用比较强,他强任他强,老子就是寸步不让.只要有这个引用在,当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不靠随意回收具有强引用的对象来解决内存不足的问题。
/**
* 强引用
*/
public static void strongReference(){
People A=new People();
Student B=new Student();
new Thread(() -> {
try {
Thread.sleep(1000);
A.name.equals(B.name);
} catch (Exception e) {
e.printStackTrace();
}
}).run();
}
如上图例子有两个实体类,主线程建立两个实体类.然后通过equals方法,A持有了B的引用,假设在没有开子线程的情况下,在主线程中A引用B 然后由于都是方法内的局部变量,那么方法执行结束,该方法退栈,引用不存在,创建的两个实体类都被释放,当在方法中启动子线程后,由于延时,A 一直对B 进行的引用那么只有在线程执行完成后才能释放引用资源.像Android常说的Handler使用不当引起的内存泄露无外乎就是这么个情况,Handler持有Activity的引用,子线程中消息又对handler持有引用,当Activity关闭的时候,由于对Activity持有引用,导致Activity不能及时释放从而导致内存泄露
软引用(SoftReference)
软引用,就是欺软怕硬呗,如果一个对象只具有软引用,则内存空间足够,gc的时候并不会回收它;如果内存空间不足了,gc的时候说兄弟没地方了把你收了,然后就收了。只要垃圾回收器没有回收它,该对象就可以被程序使用。
/**
* 软引用
*/
public static void softReference() {
People A = new People();
SoftReference<People> sf = new SoftReference<People>(A);
List<byte[]> bytes = new ArrayList<>();
while (Runtime.getRuntime().freeMemory()>64) {
byte[] b = new byte[64];
bytes.add(b);
System.out.println("循环内:"+Runtime.getRuntime().freeMemory());
}
System.out.println("循环外:"+Runtime.getRuntime().freeMemory());
People people = sf.get();
System.out.println(people==null?"null":people.name);
long freeMem=Runtime.getRuntime().freeMemory();
}
输出结果如下:
在内存严重不足马上要堆溢出的情况下,进行了gc处理 ,这个时候软引用中的对象依然别清空.
软引用可以和一个引用队列(ReferenceQueue)联合使用(和虚引用类似),如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
弱引用(WeakReference)
为啥叫弱引用,顾名思义真的弱,真的怂,只具有弱引用的对象拥有更短暂的生命周期。只要gc立马就怂,然后牺牲小我,拯救他人.
/**
* 弱引用
*/
public static void weakReference() {
People A=new People();
WeakReference<People> wf1 = new WeakReference<People>(A);
WeakReference<People> wf2 = new WeakReference<People>(new People());
A=null;//只是在弱引用的情况下 才会被回收
System.gc();
System.out.println(sf1.get());
System.out.println(sf2.get());
}
如上面方法所示,wf1是传入了A,但是由于只具有弱引用的对象才会被回收,
People A=new People()这是强引用,如果不把A的引用去掉并不会回收当前对象.wf2直接传入一对象立马就回收掉
虚引用
“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
/**
* 虚引用
*/
public static void phantomReference() {
People A=new People();
ReferenceQueue<People> queue = new ReferenceQueue<>();
PhantomReference<People> pf=new PhantomReference<>(A,queue);
People people = pf.get();
System.out.println(people==null);
}
输出结果为true
其实不光虚引用能判断对象是否回收,软引用和弱引用一样也可以不过必须联合ReferenceQueue来进行判断.