java引用类型有哪些
发布时间:2025-05-19 17:00:09 发布人:远客网络
一、java引用类型有哪些
1、Java引用类型主要有:类类型、接口类型、数组类型。
2、类类型:类是Java编程的基础,是一种引用数据类型。通过类可以创建对象实例,并通过对象的引用来访问其属性和方法。
3、接口类型:接口也是一种引用类型,它定义了一组方法,这些方法可以由任何类实现。接口用于实现多态性,允许在不同的对象上执行相同的操作。接口在Java中常被用作回调机制的一部分,允许在编译时指定协议,在运行时动态决定具体实现类。
4、数组类型:数组在Java中是一种特殊的对象,也是一种引用类型。数组用于存储固定大小的同类型元素集合,每个元素都可以通过索引来访问。数组引用本身是一个指向数组内存位置的引用变量,通过这个引用可以访问数组中的元素。
二、java中的引用数据类型是怎样的
java中有两种数据类型:基本类型和引用类型。
整数类型 byte、short、int、long
基本类型是通过诸如 int a= 5; long b= 6L;的形式来定义的,称为自动变量,自动变量存放的是字面值,不是类的实例,它存放在内存的堆栈中,数据大小和生存期必须是确定的,存取速度比较快,在堆栈中的字面值可以共享,也就是说我们定义一个int a= 5;然后又定义了一个int b= 5;这时a与b在内存中指向的是同一个字面常量。
引用类型一般是通过new关键字来创建,比如Integer num= new Integer(3);它存放在内存的堆中,可以在运行时动态的分配内存大小,生存期也不必事先告诉编译器,当引用类型变量不被使用时,Java内部的垃圾回收器GC会自动回收走。引用变量中存放的不是变量的内容,而是存放变量内容的地址。
在参数传递时,基本类型都是传值,也就是传递的都是原变量的值得拷贝,改变这个值不会改变原变量,而引用类型传递的是地址,也就是参数与原变量指向的是同一个地址,所以如果改变参数的值,原变量的值也会改变。这点要注意。
在java中,8种基本类型在java中都有对应的封装类型,也就是引用类型:
整数类型 Byte、Short、Integer、Long
有时候我们会看到这样的语句 Integer num= 3;Boolean b= true;这样定义也能行得通,其实这里面有一个自动装箱的问题,即java自动把3这个字面常量封装成了Integer对象,同理也有自动拆箱。
还有些需要注意的比较特殊的地方:
这时因为Integer的数值在-128~127之间时,即在int的范围内,默认是按照基本类型int来存放的,仍旧存在堆栈中,如果超出了int的范围,就按照对象的方式来存放和比较了。
String类型我们有时候也会直接这样定义:
这里的"abc"称为字符串常量,也是存在堆栈中的,s中存放的就是指向这个堆栈地址的引用,如果再定义一个
这时,s与s1存放的是同一个地址的引用,即s与s1指向的是同一个字符串常量,
这时s== s2则为false,因为使用new之后,每次生成的对象都不是同一个,即使存储的内容相同。
上面的s== s1,s== s2其实比较的都是地址,并不是里面的内容。如果要比较内容,可以使用equals()方法。
其他的就不多说了,打起来太慢了,可以自己去看一下java编程思想。
三、java三个引用类型
所以在 JDK.1.2之后,Java对引用的概念进行了扩充,将引用分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4种,这 4种引用的强度依次减弱。
Java中默认声明的就是强引用,比如:
Object obj= new Object();//只要obj还指向Object对象,Object对象就不会被回收
只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null,这样一来,JVM就可以适时的回收对象了
软引用是用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。
在 JDK1.2之后,用java.lang.ref.SoftReference类来表示软引用。
下面以一个例子来进一步说明强引用和软引用的区别:
在运行下面的Java代码之前,需要先配置参数-Xms2M-Xmx3M,将 JVM的初始内存设为2M,最大可用内存为 3M。
首先先来测试一下强引用,在限制了 JVM内存的前提下,下面的代码运行正常
public static void main(String[] args){
private static void testStrongReference(){
//当 new byte为 1M时,程序运行正常
byte[] buff= new byte[1024* 1024* 1];
byte[] buff= new byte[1024* 1024* 1];
替换为创建一个大小为 2M的字节数组
byte[] buff= new byte[1024* 1024* 2];
则内存不够使用,程序直接报错,强引用并不会被回收
接着来看一下软引用会有什么不一样,在下面的示例中连续创建了 10个大小为 1M的字节数组,并赋值给了软引用,然后循环遍历将这些对象打印出来。
private static List<Object> list= new ArrayList<>();
public static void main(String[] args){
private static void testSoftReference(){
for(int i= 0; i< 10; i++){
byte[] buff= new byte[1024* 1024];
SoftReference<byte[]> sr= new SoftReference<>(buff);
System.gc();//主动通知垃圾回收
for(int i=0; i< list.size(); i++){
Object obj=((SoftReference) list.get(i)).get();
我们发现无论循环创建多少个软引用对象,打印结果总是只有最后一个对象被保留,其他的obj全都被置空回收了。
这里就说明了在内存不足的情况下,软引用将会被自动回收。
值得注意的一点,即使有 byte[] buff引用指向对象,且 buff是一个strong reference,但是 SoftReference sr指向的对象仍然被回收了,这是因为Java的编译器发现了在之后的代码中, buff已经没有被使用了,所以自动进行了优化。
如果我们将上面示例稍微修改一下:
private static void testSoftReference(){
for(int i= 0; i< 10; i++){
SoftReference<byte[]> sr= new SoftReference<>(buff);
System.gc();//主动通知垃圾回收
for(int i=0; i< list.size(); i++){
Object obj=((SoftReference) list.get(i)).get();
System.out.println("buff:"+ buff.toString());
则 buff会因为强引用的存在,而无法被垃圾回收,从而抛出OOM的错误。
如果一个对象惟一剩下的引用是软引用,那么该对象是软可及的(softly reachable)。垃圾收集器并不像其收集弱可及的对象一样尽量地收集软可及的对象,相反,它只在真正“需要”内存时才收集软可及的对象。
弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM开始进行垃圾回收,那些被弱引用关联的对象都会被回收。在 JDK1.2之后,用 java.lang.ref.WeakReference来表示弱引用。
我们以与软引用同样的方式来测试一下弱引用:
private static void testWeakReference(){
for(int i= 0; i< 10; i++){
byte[] buff= new byte[1024* 1024];
WeakReference<byte[]> sr= new WeakReference<>(buff);
System.gc();//主动通知垃圾回收
for(int i=0; i< list.size(); i++){
Object obj=((WeakReference) list.get(i)).get();
可以发现所有被弱引用关联的对象都被垃圾回收了。
虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收,在 JDK1.2之后,用 PhantomReference类来表示,通过查看这个类的源码,发现它只有一个构造函数和一个 get()方法,而且它的 get()方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象,虚引用必须要和 ReferenceQueue引用队列一起使用。
public class PhantomReference<T> extends Reference<T>{
* Returns this reference object's referent. Because the referent of a
* phantom reference is always inaccessible, this method always returns
*<code>null</code>.
*@return<code>null</code>
public PhantomReference(T referent, ReferenceQueue<? super T> q){
那么传入它的构造方法中的 ReferenceQueue又是如何使用的呢?
五,引用队列(ReferenceQueue)
引用队列可以与软引用、弱引用以及虚引用一起配合使用,当垃圾回收器准备回收一个对象时,如果发现它还有引用,那么就会在回收对象之前,把这个引用加入到与之关联的引用队列中去。程序可以通过判断引用队列中是否已经加入了引用,来判断被引用的对象是否将要被垃圾回收,这样就可以在对象被回收之前采取一些必要的措施。