1.什么是引用?
简单的说,引用是一个对象别名,与被引用的对象共享同一块内存区域。例如“鹿晗”这个对象,他的原名是“刘壮实”,但两者其实都是指同一个人(内存)。对象在创建时会请求一块内存空间来保存数据,会根据对象大小分配存储空间大小不等的内存区域。在Java中,访问对象时,不会直接访问对象在内存中的数据,而是通过引用去访问。因此,引用也是一种数据类型,类似于C/C++ 语言中的指针。引用定义时在栈中分配内存,引用变量在程序运行到作用域外释。
注意:引用可以独立存在,并不一定依赖于一个对象,例如:
String str;
2.引用类型和值类型的区别?
2.1 值传递-基本类型作为参数传递
public class Main {
public static void main(String[] args) {
int n = 30;
System.out.println("Before change, n = " + n);
changeVal(n);
System.out.println("After change, n = " + n);
}
public static void changeVal(int m) {
m = 10;
}
}
程序运行的结果如下:
Before change, n = 30
After change, n = 30
因此可以看出,基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的。
2.2 引用类型传递
import java.util.*;
public class Main {
public static void main(String[] args)
{
StringBuffer sb = new StringBuffer("Hello ");
System.out.println("Before change, sb = " + sb);
changeReference(sb);
System.out.println("After change, sb = " + sb);
}
public static void changeReference(StringBuffer sBuffer)
{
sBuffer.append("World!");
}
}
程序运行的结果如下:
Before change, sb = Hello
After change, sb = Hello World!
从程序运行的结果来看,sb的值被改变了,在Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数。
3.Java四种类型的引用
- 强引用
在Java 中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到JVM也不会回收。因此强引用是造成Java 内存泄漏的主要原因之一。
在java中,默认的引用声明就是强引用,例如:
String str = new String();
str = null;
-
软引用
软引用需要用SoftReference 类来实现,对于只有软引用的对象来说,当系统内存足够时它不会被回收,当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中。 -
弱引用
弱引用需要用WeakReference 类来实现,它比软引用的生存期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管JVM 的内存空间是否足够,总会回收该对象占用的内存。 -
虚引用
虚引用需要PhantomReference 类来实现,它不能单独使用,必须和引用队列联合使用。虚引用的主要作用是跟踪对象被垃圾回收的状态。