java的引用类型共四种
1:强引用
2:软引用
3:弱引用
4:虚引用
什么是强引用?
在java中普遍情况下我们会直接new Object(); 这种写法来创建一个对象 这种写法通常就是所谓的强引用,强引用的特别之处在于 假设当前程序即将OOM 那么在OOM来临 JVM会保证进行一次GC 当GC遇到强引用的对象 宁愿OOM也不会去回收该对象。当然 我们可以手动对该对象置空 或者 超出作用域时 GC就会对这类对象进行回收。
//code public static void main(String[] args) { Object o = new Object();//一个强引用对象 o=null;//同样 gc来了 会回收 } public static void test(){ //超出了作用域的对象 会被gc来临时 Object o = new Object(); } 复制代码
什么是软引用?
在Java中 用SoftReference 关键字包裹的对象就是一个软引用比如
SoftReference<byte[]> softReference = new SoftReference(new byte[1024]);///这是一个软引用对象 复制代码
软引用对象的特点是 在JVM即将OOM前 JVM会保证进行一次GC 那么当GC遇到当前对象只剩软引用的话 就会对它进行回收 通俗的说 一个对象只能软引用引用的话 就会在内存不足的情况下被回收
SoftReference<byte[]> softReference = new SoftReference(new byte[1024]); System.out.println(softReference.get().length); ///假设我们再创建bytes对象时 内存不足了 这个时候 JVM会让GC干活 GC扫描到软引用对象 就会回收 byte[] bytes = new byte[1024]; System.out.println(softReference.get());//这个时候 再次 get 就会为空 复制代码
为了更好理解只剩一个对象引用
byte[] b = new byte[1024]; SoftReference<byte[]> softReference = new SoftReference(b); System.out.println(softReference.get().length); ///假设我们再创建bytes对象时 这个时候 由于b对象不是只有一个引用 它有一个强引用 和一个软引用 我们的内存不足以创建 bytes时 就会触发OOM byte[] bytes = new byte[1024]; 复制代码
什么是弱引用?
弱引用是一个比软引用还是"软"的引用 软引用可以看成是 弱引用的plus版本。 弱引用的特点是:当对象只剩一个弱引用对象时 任何时候 GC只要一遇到弱引用对象 就会对它进行回收。
WeakReference<byte[]> weakReference = new WeakReference(new byte[1024]); System.out.println(weakReference.get().length); System.gc(); System.out.println(weakReference.get());/// null 因为被gc了 复制代码
什么是虚引用?
虚引用是四大引用中最弱的一种 它有一个特点 就是 无法通过get方法获取引用的对象
public class PhantomReference<T> extends Reference<T> { public T get() { return null;///get 方法 永远返回的是null。所以我们无法获取对象 } public PhantomReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } } 复制代码
而且虚引用在创建时 必须需要传入一个ReferenceQueue(引用队列) 而这个引用队列 会在对象销毁时 添加到这个队列里。
java中就时用虚引用管里堆外内存的 。( 知识点来自:马士兵java)
引用的特例
在之前测试时 为发现一个非常基础的知识被我遗忘了
WeakReference<Integer> wr1 = new WeakReference(new Integer(123)); WeakReference<Integer> wr2 = new WeakReference(123); System.gc(); System.out.println(wr1.get());//会打印出null System.out.println(wr2.get());//会打印出123 复制代码
如果你不知道为什么 可能需要继续往下看
其实很简单 在Java中 有缓存池的概念。一些常用的基础类型 会存储在这些缓存池中 比如说下面类型:
String str = "123";//java会在字符串缓存池 寻找相同的 如果没有就创建 有的直接引用 int i = 123;// int 会缓存 -128 到 127 间的所有数字 byte;//会缓存所有的byte boolean; //同样会缓存所有的值 当然 也只有false true
作者:FeanCheng
链接:https://juejin.cn/post/6844904136090075150
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。