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

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软应用尚未实现,

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

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

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

那么我们就来试试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行也说明了这一点。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 引用的分类 Java 1.2以后,除了普通的引用外,Java还定义了软引用、弱引用、虚引用等概念。 强引用:GC ...
    刘惜有阅读 755评论 0 1
  • 1 Java的引用 对于Java中的垃圾回收机制来说,对象是否被应该回收的取决于该对象是否被引用。因此,引用也是J...
    高级java架构师阅读 369评论 0 1
  • 退之平生多得謗譽 退之诗云:「我生之辰,月宿南斗。」乃知退之磨蝎为身宫,而仆乃以磨蝎为命,平生多得谤誉,殆是同...
    台灯好亮阅读 1,653评论 0 0
  • 已经读完了《App研发录》第一章,并且对整本书有了一个大致了解。我觉得有必要记录一下,对于架构方面,很多问题第一次...
    罗罗罗罗罗sky阅读 285评论 0 1
  • 大家好 我是青岛金典广告的王新涛,今天是2019年06月13日,我的日精进行动第157天,和大家分享我今天的进步,...
    金典广告阅读 272评论 0 0