5.WeakHashMap
WeakHashMap是一种弱引用的HashMap,指的是key值如果没有外部强引用后,在垃圾回收的时候会被收掉。
引用类型
官方文档对引用类型类的描述
Provides reference-object classes, which support a limited degree of interaction with the garbage collector. A program may use a reference object to maintain a reference to some other object in such a way that the latter object may still be reclaimed by the collector. A program may also arrange to be notified some time after the collector has determined that the reachability of a given object has changed.
提供引用对象类,该类支持与垃圾收集器进行有限程度的交互。程序可以使用一个引用对象来维护对其他一些对象的引用,这样后一个对象仍然可以被收集器回收。程序也可以安排在收集器确定给定对象的可达性发生改变后的一段时间内收到通知。
我理解的就是一个箱子,里面装上你要装的对象,这个箱子与辣鸡回收器有直接的交互,可以控制对引用对象的回收。
ReferenceQueue,引用队列,在检测到适当的可达性更改后,垃圾收集器将向其添加已注册的引用对象
WeakReference,弱引用,当弱引用没有外部强引用的引用时,会被垃圾回收机制回收。
SoftReference,软引用,与软引用一致,但回收会被延迟,在
PhantomReference,虚引用,使用虚引用的目的就是为了得知对象被GC的时机,所以可以利用虚引用来进行销毁前的一些操作,比如说资源释放等。这个虚引用对于对象而言完全是无感知的,有没有完全一样,但是对于虚引用的使用者而言,就像是待观察的对象的把脉线,可以通过它来观察对象是否已经被回收,从而进行相应的处理。
这个问题的答案来自这个博客你不可不知的Java引用类型之——虚引用 - 弗兰克的猫 - 博客园 (cnblogs.com)
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
class Demo1 {
public String name;
public String content;
public Demo1(String name, String content){
this.name = name;
this.content = content;
}
public static void main(String[] args) {
ReferenceQueue referenceQueue = new ReferenceQueue();
WeakReference<Demo1> weakReference
= new WeakReference<Demo1>(new Demo1("name1","弱引用"),referenceQueue);
SoftReference<Demo1> softReference
= new SoftReference<Demo1>(new Demo1("name3","软引用"));
PhantomReference<Demo1> phantomReference
= new PhantomReference<Demo1>(new Demo1("name2","虚引用"),referenceQueue);
System.out.println(weakReference.get());
System.out.println(softReference.get());
System.out.println(phantomReference.get());
System.out.println("====gc之后====");
System.gc();
System.out.println(weakReference.get());
System.out.println(softReference.get());
System.out.println(phantomReference.get());
}
}
结果:
demo.Demo1@74a14482
demo.Demo1@1540e19d
null
====gc之后====
null
demo.Demo1@1540e19d
null
第一个是弱引用,第二个是软引用,第三个是虚引用。
继续研究WeakHashMap
Hash table based implementation of the
Map
interface, with weak keys. An entry in aWeakHashMap
will automatically be removed when its key is no longer in ordinary use.
所以WeakHashMap就是在HashMap的基础上,多了个键值对不被引用的情况下会被辣鸡回收器收回。
先使用一下康康。
public static void main(String[] args) {
WeakHashMap<Integer,Integer> weakHashMap = new WeakHashMap<>();
weakHashMap.put(1,1);
System.gc();
System.out.println(weakHashMap.isEmpty());
}
结果:
false
果然,那点进去看看怎么实现的。
//并没有什么特殊的,点开Entry康康
public V put(K key, V value) {
Object k = maskNull(key);
int h = hash(k);
Entry<K,V>[] tab = getTable();
int i = indexFor(h, tab.length);
for (Entry<K,V> e = tab[i]; e != null; e = e.next) {
if (h == e.hash && eq(k, e.get())) {
V oldValue = e.value;
if (value != oldValue)
e.value = value;
return oldValue;
}
}
modCount++;
Entry<K,V> e = tab[i];
tab[i] = new Entry<>(k, value, queue, h, e);
if (++size >= threshold)
resize(tab.length * 2);
return null;
}
//Entry继承了WeakReference,构建Entry的时候,会交给服了WeakReference来构建,这样就实现了键值对对象的弱引用
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
V value;
final int hash;
Entry<K,V> next;
/**
* Creates new entry.
*/
Entry(Object key, V value,
ReferenceQueue<Object> queue,
int hash, Entry<K,V> next) {
//交给父类来实现。
super(key, queue);
this.value = value;
this.hash = hash;
this.next = next;
}
@SuppressWarnings("unchecked")
public K getKey() {
return (K) WeakHashMap.unmaskNull(get());
}
public V getValue() {
return value;
}
public V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
K k1 = getKey();
Object k2 = e.getKey();
if (k1 == k2 || (k1 != null && k1.equals(k2))) {
V v1 = getValue();
Object v2 = e.getValue();
if (v1 == v2 || (v1 != null && v1.equals(v2)))
return true;
}
return false;
}
public int hashCode() {
K k = getKey();
V v = getValue();
return Objects.hashCode(k) ^ Objects.hashCode(v);
}
public String toString() {
return getKey() + "=" + getValue();
}
}
所以WeakHashMap在HashMap的基础上,通过让Entry继承WeakReference来达到键值对称为弱引用的目的,实现键值对不被引用就被辣鸡回收器回收的功能。