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软应用尚未实现,
在系统里只有个空的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行也说明了这一点。
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:


Java和ABAP中的几种引用类型的分析和比较的更多相关文章
- Java中的四种引用类型比较
1.引用的概念 引用这个概念是与JAVA虚拟机的垃圾回收有关的,不同的引用类型对应不同的垃圾回收策略或时机. 垃圾收集可能是大家感到难于理解的较难的概念之一,因为它并不能总是毫无遗漏地解决Java运行 ...
- Java 并发包中的读写锁及其实现分析
1. 前言 在Java并发包中常用的锁(如:ReentrantLock),基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时 刻可以允许多个读线程访问,但是在写线程访问时,所有 ...
- Java 中的四种引用类型(转)
目录 背景 简介 1. 强引用 StrongReference 2. 弱引用 WeakReference 3. 软引用 SoftReference ...
- Java中的四种引用类型,强引用,软引用,弱引用,虚引用
对于Java中的垃圾回收机制来说,对象是否被回收的标准在于该对象是否被引用.因此,引用也是JVM进行内存管理的一个重要概念. Java中对象的引用一般有以下4种类型: 1强引用 2软引用 3弱引用 ...
- java中的四种引用类型
为什么需要引用: Java的内存回收不需要程序员负责,JVM会在必要时启动Java GC完成垃圾回收. Java以便我们控制对象的生存周期,提供给了我们四种引用方式,引用强度从强到弱分别为:强引用.软 ...
- 关于Java集合类库中的几种常用队列
Java中几种常用的队列 阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞.试图从空的阻塞队列中获取元素的线程将会被阻塞 ...
- java.util.concurrent中的几种同步工具类
java.util.concurrent并发包中提供了一系列的的同步工具类,这些基础类不管是否能在项目中使用到,了解一下使用方法和原理对java程序员来说都是有必要的.博主在看<java并发编程 ...
- 【Java】NIO中Selector的创建源码分析
在使用Selector时首先需要通过静态方法open创建Selector对象 public static Selector open() throws IOException { return Sel ...
- 【Java】NIO中Channel的注册源码分析
Channel的注册是在SelectableChannel中定义的: public abstract SelectionKey register(Selector sel, int ops, Obje ...
随机推荐
- 《精通Spring4.X企业应用开发实战》读后感第五章(注入参数详解)
- HDU - 6415 多校9 Rikka with Nash Equilibrium(纳什均衡+记忆化搜索/dp)
Rikka with Nash Equilibrium Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K ...
- GPLT天梯赛 L2-022. 重排链表
L2-022. 重排链表 时间限制 500 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定一个单链表 L1→L2→...→Ln-1→Ln,请 ...
- 使用gRPC搭建Server端与Client端
gRPC简介 gRPC是一种RPC框架技术,采用Protocal Buffers(协议缓存) 作为其接口定义的语言(就是Proto来写接口)和基础的消息交换格式. 在gRPC中,客户端应用程序可以直接 ...
- 数据库路由中间件MyCat - 源代码篇(5)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3. 连接模块 如之前所述,MyCat的连接分为前端和后端,下面是连接基本相关类图: 3.1 Closabl ...
- 2015 Noip提高组 Day1
P2615 神奇的幻方 [题目描述] 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: ...
- IT兄弟连 JavaWeb教程 过滤器与监听器经典面试题
1.谈谈你对Servlet过滤器的理解 过滤器是Servlet2.3规范中定义的一种小型的.可插入的Web组件.用来拦截Servlet容器的请求和响应过程,以便查看.提取客户端和服务器之间正在交换的数 ...
- 剑指Offer的学习笔记(C#篇)-- 整数中1出现的次数(从1到n整数中1出现的次数)
题目描述 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了. ...
- 外网连接Mysql云数据库
购买好Mysql云数据库,这里是腾讯云 在管理中把外网地址开通,然后可以看到本云数据库的外网地址 注意:外网地址com到前面才是连接地址,冒号后面的10057是连接的端口号,可以看下面的连接语句 cm ...
- plsql developer 执行sql 文件
用 Command Window,执行 @'sql file path' 注意,上面sql文件路径要加单引号