Java强、弱、软、虚四种引用

值类型和引用类型

在Java中类型可分为两大类:值类型引用类型。值类型就是基本数据类型(如int ,double 等),而引用类型,是指除了基本的变量类型之外的所有类型(如通过 class 定义的类型)。值类型只有一块存储空间,分配在 stack中,而引用类型有两块存储空间,存储引用的空间分配在 stack 上,存储引用所指向的对象空间分配在 heap 中,引用中保存了对象在 heap 中的地址。
java类型的内存表示

对象的传参方式

首选,这里所说的对象包括了基本数据类型自定义数据类型(类),因为 java 中一切皆对象。

当把对象作为参数传递给函数后,函数对形参的更改会不会影响原对象呢?这个问题就引出了 java 是“值传递”还是“引用传递”的问题。

考虑下面的代码:

public class referenceTest {
    //交换两个变量的值

    public static void Swap(int a,int b){
       int c=a;
       a=b;
       b=c;
       System.out.println("a: " + a);
       System.out.println("b: " + b);
    }

    public static void main(String[] args){
       int c=10;
       int d=20;
       Swap(c,d);
       System.out.println("After Swap:");
       System.out.println("c: "+ c);
       System.out.println("d: "+ d);
    }
}

输出:

a: 20
b: 10
After Swap:
c: 10
d: 20

Swap 对形参的改变并没有改变传入的实参,所以这里是按“值传递”的。

事实上,从上面的图中可以看出,java 中基本数据类型在参数传递的时候是传入的原参数的一个拷贝,函数内部的改变只会改变拷贝值而不会改变原值。而自定义数据类型则不同。从图中可以看出,传参的时候,对引用进行了拷贝传入函数,但是引用指向的却是原来的对象,这个时候如果在函数中对对象进行更改则会影响函数外面的对象,所以这里可以说是“引用传递”

回到上面的代码,如果我们真的想通过一个函数交换两个基本类型的值应该怎么办呢?两个方法:

  1. 把所有变量封装到类中去
  2. 通过数组可以方便的实现值类型的数据源的交换

java中的四种引用类型

分别是指强引用、软引用、弱引用和虚引用

强引用(StrongReference)

强引用就是普通引用,也是平时使用最多的一种引用方式。只要某个对象有强引用与之关联,在内存不足的情况下,JVM 宁愿抛出OutOfMemory错误也不会回收这种对象。

软引用(SoftReference)

Java 中用java.lang.ref.SoftReference类来表示软引用。对于软引用关联着的对象,只有在内存不足的时候 JVM 才会回收该对象。

SoftReference<String> sr = new SoftReference<String>(new String("hello"));
System.out.println(sr.get());

其中get方法用来获取与软引用关联的对象的引用,如果该对象被回收了,则返回 null

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被 JVM 回收,这个软引用就会被加入到与之关联的引用队列中

应用场景: 软引用通常用来实现内存敏感的缓存

弱引用(WeakReference)

java中,用java.lang.ref.WeakReference类来表示弱引用,它用来描述非必需对象的,当 JVM 进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被 JVM 回收,这个软引用就会被加入到与之关联的引用队列中

应用场景: 弱引用同样通常用来实现内存敏感的缓存。

虚引用(PhantomReference)

虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。在 java 中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。

虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

应用场景:可用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知。


文章作者: 木白
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 木白 !
  目录