ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java 和 ABAP 中的几种引用类型的分析和比较

2021-12-07 11:34:37  阅读:194  来源: 互联网

标签:Java lo System 几种 person ABAP 引用 PhantomReference


Java 编程语言中几种不同的引用类型是面试时经常容易被问到的问题:强引用,软引用,弱引用,虚引用。

其实除了 Java 之外,某些 其他编程语言也有类似概念,比如 ABAP。今天我们就来比较一下。

根据 ABAP 帮助文档,我们可以把某个对象的引用包在一个 Weak Reference 的实例里。ABAP 的 Weak Reference 实例通过类 CL_ABAP_WEAK_REFERENCE 实现。

看下面的例子:首先我在堆上创建了一个新的 LCL_PERSON 实例,然后包到一个 ABAP weak reference 里。

lo_person = NEW lcl_person( 'Jerry' ).

lo_weak = NEW cl_abap_weak_reference( lo_person ).

稍后,我们想拿到被包裹的 lo_person 引用时,使用 weak reference 提供的 get 方法。见下图示例:

lo_person = CAST lcl_person( lo_weak->get( ) ).

引用 lo_person 什么时候会变成 initial 呢?如果当 ABAP 垃圾回收器(Garbage Collector)开始工作时,已经没有任何引用再指向 lo_person, 则 lo_person 会变成 initial。

看下面这个例子加深理解。

REPORT ztest.

PARAMETERS: clear TYPE char1 as CHECKBOX DEFAULT abap_true,

gc TYPE char1 as CHECKBOX DEFAULT abap_true.

CLASS lcl_person DEFINITION.

PUBLIC SECTION.

DATA: mv_name TYPE string.

METHODS: constructor IMPORTING !iv_name TYPE string.

ENDCLASS.

CLASS lcl_person IMPLEMENTATION.

METHOD: constructor.

me->mv_name = iv_name.

ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

DATA: lo_person TYPE REF TO lcl_person,

lo_weak TYPE REF TO cl_abap_weak_reference.

lo_person = NEW lcl_person( 'Jerry' ).

lo_weak = NEW cl_abap_weak_reference( lo_person ).

IF clear = abap_true.

CLEAR: lo_person.

ENDIF.

IF gc = abap_true.

cl_abap_memory_utilities=>do_garbage_collection( ).

ENDIF.

lo_person = CAST lcl_person( lo_weak->get( ) ).

IF lo_person IS INITIAL.

WRITE: / 'reference not available'.

ELSE.

WRITE: / 'reference still available'.

ENDIF.

这个 report 有两个开关,如下图。第一个开关控制 lo_person 这个引用是否被关键字 CLEAR 显式地置为 INITIAL, 第二个开关决定是否在代码中显式地调用 ABAP 垃圾回收器。

这两个开关的打开和关闭状态,一共有 4 种组合。

在第一种情况下,通过关键字 CLEAR 清除了 lo_person 的引用,从 ABAP 的内存检查器(事务码 s_memory_inspector)能发现,lo_person 现在已经不指向任何内存中的对象了。

对于其他三种情况,LCL_PERSON 的实例都不会被 ABAP 垃圾回收器清除:

Java

Java培训 中的 weak reference 表现行为和 ABAP 一致。

我把上面的 ABAP 测试代码用 Java 程序重新写一遍:


import java.lang.ref.WeakReference;

class Person {

  private String mName;

  public Person(String name) {

    this.mName = name;

  }

  public String getName() {

    return this.mName;

  }

}

public class WeakReferenceTest {

  public static void check(Person person) {

    if (person == null) {

      System.out.println("Reference invalid");

    }

    else {

      System.out.println("Reference still available");

    }

  }

  public static void main(String[] args) {

    Person jerry = null;

    WeakReference<Person> person = new WeakReference<Person>(new Person(
        "Jerry"));

    jerry = new Person("Ben");

    // if you comment out this line, Reference will be available

    System.gc();

    Person restore = person.get();

    check(restore);

  }

}

ABAP Soft reference - ABAP 软应用

在我目前使用的 ABAP Netweaver 750 SP4 系统中,ABAP 软应用尚未实现,

在系统里只有个空的 CL_ABAP_SOFT_REFERENCE, 其描述信息写的是 Do Not Use this Class!

那么我们就来试试 Java 的软应用 Soft Reference:

package reference;

import java.lang.ref.SoftReference;

import java.util.ArrayList;

class Person2 {

  private String mName;

  public Person2(String name) {

    this.mName = name;

  }

  public String getName() {

    return this.mName;

  }

  public void finalize() {

    System.out.println("finalize called: " + this.mName);

  }

  public String toString() {

    return "Hello, I am " + this.mName;

  }

}

public class SoftReferenceTest {

  public static void main(String[] args) {

    SoftReference<Person2> person = new SoftReference<Person2>(new Person2(
        "Jerry"));

    System.out.println(person.get());

    ArrayList<Person2> big = new ArrayList<Person2>();

    for (int i = 0; i < 10000; i++) {

      big.add(new Person2(String.valueOf(i)));

    }

    System.gc();

    System.out.println("End: " + person.get());

  }

}

控制台打印出的输出:

Hello, I am Jerry

End: Hello, I am Jerry

即便我创建了 1 万个 Person 对象的实例,确实消耗了一些内存,然后内存消耗还远远没有大到会导致包含在软应用中的 Person2 类的引用被 JDK 删除掉的程度。因此我在代码中调用 Java 的垃圾回收器 System.gc()之后,该引用仍然存在。

在 Java 中,软应用通常被用来实现在内存资源很有限的环境下的缓存机制,比如 Android 手机开发中。

Java 虚引用 PhantomReference

使用下面的代码测试虚引用:

package aop;

import java.lang.ref.PhantomReference;

import java.lang.ref.ReferenceQueue;

public class PhantomReferenceTest {

  public static void main(String[] args) {

    Object phantomObj;

    PhantomReference phantomRef, phantomRef2;

    ReferenceQueue phantomQueue;

    phantomObj = new String("Phantom Reference");

    phantomQueue = new ReferenceQueue();

    phantomRef = new PhantomReference(phantomObj, phantomQueue);

    System.out.println("1 Phantom Reference:" + phantomRef.get());

    System.out.println("2 Phantom Queued: " + phantomRef.isEnqueued());

    phantomObj = null;

    System.gc();

    System.out.println("3 Anything in Queue? : " + phantomQueue.poll());

    if (!phantomRef.isEnqueued()) {

      System.out.println("4 Requestion finalization.");

      System.runFinalization();

    }

    System.out.println("5 Anything in Queue?: " + phantomRef.isEnqueued());

    phantomRef2 = (PhantomReference) phantomQueue.poll();

    System.out.println("6 Original PhantomReference: " + phantomRef);

    System.out.println("7 PhantomReference from Queue: " + phantomRef2);

  }
}

测试输出:

1. Phantom Reference: null

2. Phantom Queued: false

3. Anything in Queue? : null

5. Anything in Queue?: true

6. Original PhantomReference: java.lang.ref.PhantomReference@2a139a55

7. PhantomReference from Queue: java.lang.ref.PhantomReference@2a139a55

和之前介绍的弱引用(WeakReference)和软引用(SoftReference)不同,包裹在虚引用(PhantomReference)中的对象实例无法通过需引用的 get 方法返回,因此在第一行输出我们会看到: “1. Phantom Reference: null”.

在上面示例代码中虚引用 PhantomReference 的构造函数里, 我传入了一个队列作为输入参数。当包裹在虚引用实例中的对象引用被 Java 垃圾回收器删除时,虚引用实例本身会自动被 JVM 插入我之前指定到虚引用构造函数输入参数的那个队列中去。

在 System.runFinalization()执行之前,phantomRef.isEnqueued()返回 false,phantomQueue.poll()返回空。

当 phantomObj 实例被 JVM 删除后, 虚引用 PhantomReference 本身被加入到队列中,并且能够通过队列提供的 API 所访问:phantomQueue.poll(). 打印输出的第 6 行和第 7 行也说明了这一点。

标签:Java,lo,System,几种,person,ABAP,引用,PhantomReference
来源: https://blog.csdn.net/zjjcchina/article/details/121764548

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有