深入理解Java引用类型

目录

  • 什么是引用?
  • 四种引用类型
    • 一,强引用
    • 二,软引用
    • 三,弱引用
    • 四,虚引用

在Java中类型可分为两大类:值类型与引用类型。值类型就是基本数据类型(如int ,double 等),而引用类型,是指除了基本的变量类型之外的所有类型。基本变量类型只有一块存储空间(分配在stack中), 而引用类型有两块存储空间一块在stack(栈)中,一块在heap(堆)中。

什么是引用?

每种编程语言都有自己操作内存中元素的方式,例如在 C 和 C++ 里是通过指针,而在 Java 中则是通过“引用”。
在 Java 中一切都被视为了对象,但是我们操作的标识符实际上是对象的一个引用(reference)。

//创建一个引用,引用可以独立存在,并不一定需要与一个对象关联
String s;

通过将这个叫“引用”的标识符指向某个对象,之后便可以通过这个引用来实现操作对象了。

String yy = new String("引用");
System.out.println(yy.toString());

JDK1.2 之前,一个对象只有“已被引用”和"未被引用"两种状态,这将无法描述某些特殊情况下的对象,比如,当内存充足时需要保留,而内存紧张时才需要被抛弃的一类对象。
在 JDK1.2 之前,Java中的定义很传统:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称为这块内存代表着一个引用。

Java 中的垃圾回收机制在判断是否回收某个对象的时候,都需要依据“引用”这个概念。
在不同垃圾回收算法中,对引用的判断方式有所不同:

  • 引用计数法:为每个对象添加一个引用计数器,每当有一个引用指向它时,计数器就加1,当引用失效时,计数器就减1,当计数器为0时,则认为该对象可以被回收(目前在Java中已经弃用这种方式了)。
  • 可达性分析算法:从一个被称为 GC Roots 的对象开始向下搜索,如果一个对象到GC Roots没有任何引用链相连时,则说明此对象不可用。

四种引用类型

JDK.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种,这 4 种引用的强度依次减弱。

深入理解Java引用类型_第1张图片

一,强引用

一个对象赋给一个引用就是强引用,比如new一个对象,一个对象被赋值一个对象。

Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收
obj = null; //手动置null

只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null,这样一来,JVM就可以适时的回收对象了。

二,软引用

用SoftReference类实现,一般不会轻易回收,只有内存不够才会回收。

软引用是用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。
在 JDK1.2 之后,用java.lang.ref.SoftReference类来表示软引用。

public class Test{
public static void main(String[] args) {
String ss = "hello,World";
//这时"hello,World"有一个强引用, 还有一个软引用
//泛型指的是软引用指向的类型
//软引用是内存不足时,对象被回收
SoftReference soft = new SoftReference(ss);
//获取软引用的对象
String content = soft.get();
System.out.println(content);

三,弱引用

用WeekReference类实现,一旦垃圾回收已启动,就会回收。
弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。

public class WeakReference {
public static void main(String[] args) {
String ss = "hello";
ReferenceQueue queue = new ReferenceQueue<>();
java.lang.ref.WeakReference weak = new
java.lang.ref.WeakReference(ss,queue);
System.out.println("现在的引用 " + weak.get());
ss = null;
System.gc(); //gc
Reference poll = queue.poll(); //如果null,说明被回收了
if(poll != null) {
String content = poll.get();
System.out.println(content);
} //看看有没有被回收
}
}

四,虚引用

不能单独存在,必须和引用队列联合使用。主要作用是跟踪对象被回收的状态。

虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收,在 JDK1.2 之后,用 PhantomReference 类来表示,通过查看这个类的源码,发现它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象,虚引用必须要和 ReferenceQueue 引用队列一起使用。

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class Main {
public static void main(String[] args) {
ReferenceQueue queue = new ReferenceQueue();
PhantomReference pr = new PhantomReference(newString("hello"), queue);
System.out.println(pr.get());
}

你可能感兴趣的:(#,Java基础入门,java,jvm,开发语言,引用)