Java和ABAP中的几种引用类型的分析和比较
Java編程語(yǔ)言中幾種不同的引用類(lèi)型是面試時(shí)經(jīng)常容易被問(wèn)到的問(wèn)題:強(qiáng)引用,軟引用,弱引用,虛引用。
其實(shí)除了Java之外,某些 其他編程語(yǔ)言也有類(lèi)似概念,比如ABAP。今天我們就來(lái)比較一下。
根據(jù)ABAP幫助文檔,我們可以把某個(gè)對(duì)象的引用包在一個(gè)Weak Reference的實(shí)例里。ABAP的Weak Reference實(shí)例通過(guò)類(lèi)CL_ABAP_WEAK_REFERENCE實(shí)現(xiàn)。
看下面的例子:首先我在堆上創(chuàng)建了一個(gè)新的LCL_PERSON實(shí)例,然后包到一個(gè)ABAP weak reference里。
lo_person = NEW lcl_person( ‘Jerry’ ).
lo_weak = NEW cl_abap_weak_reference( lo_person ).
稍后,我們想拿到被包裹的lo_person引用時(shí),使用weak reference提供的get方法。見(jiàn)下圖示例:
lo_person = CAST lcl_person( lo_weak->get( ) ).
引用lo_person什么時(shí)候會(huì)變成initial呢?如果當(dāng)ABAP垃圾回收器(Garbage Collector)開(kāi)始工作時(shí),已經(jīng)沒(méi)有任何引用再指向lo_person, 則lo_person會(huì)變成initial。
看下面這個(gè)例子加深理解。
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.這個(gè)report有兩個(gè)開(kāi)關(guān),如下圖。第一個(gè)開(kāi)關(guān)控制lo_person這個(gè)引用是否被關(guān)鍵字CLEAR顯式地置為INITIAL, 第二個(gè)開(kāi)關(guān)決定是否在代碼中顯式地調(diào)用ABAP垃圾回收器。
這兩個(gè)開(kāi)關(guān)的打開(kāi)和關(guān)閉狀態(tài),一共有4種組合。
在第一種情況下,通過(guò)關(guān)鍵字CLEAR清除了lo_person的引用,從ABAP的內(nèi)存檢查器(事務(wù)碼s_memory_inspector)能發(fā)現(xiàn),lo_person現(xiàn)在已經(jīng)不指向任何內(nèi)存中的對(duì)象了。
對(duì)于其他三種情況,LCL_PERSON的實(shí)例都不會(huì)被ABAP垃圾回收器清除:
Java
Java中的weak reference表現(xiàn)行為和ABAP一致。
我把上面的ABAP測(cè)試代碼用Java程序重新寫(xiě)一遍:
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 availableSystem.gc();Person restore = person.get();check(restore);}}ABAP Soft reference - ABAP軟應(yīng)用
在我目前使用的ABAP Netweaver 750 SP4系統(tǒng)中,ABAP軟應(yīng)用尚未實(shí)現(xiàn),
在系統(tǒng)里只有個(gè)空的CL_ABAP_SOFT_REFERENCE, 其描述信息寫(xiě)的是Do Not Use this Class!
那么我們就來(lái)試試Java的軟應(yīng)用 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());}}控制臺(tái)打印出的輸出:
Hello, I am Jerry
End: Hello, I am Jerry
即便我創(chuàng)建了1萬(wàn)個(gè)Person對(duì)象的實(shí)例,確實(shí)消耗了一些內(nèi)存,然后內(nèi)存消耗還遠(yuǎn)遠(yuǎn)沒(méi)有大到會(huì)導(dǎo)致包含在軟應(yīng)用中的Person2類(lèi)的引用被JDK刪除掉的程度。因此我在代碼中調(diào)用Java的垃圾回收器System.gc()之后,該引用仍然存在。
在Java中,軟應(yīng)用通常被用來(lái)實(shí)現(xiàn)在內(nèi)存資源很有限的環(huán)境下的緩存機(jī)制,比如Android手機(jī)開(kāi)發(fā)中。
Java 虛引用 PhantomReference
使用下面的代碼測(cè)試虛引用:
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);} }測(cè)試輸出:
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)中的對(duì)象實(shí)例無(wú)法通過(guò)需引用的get方法返回,因此在第一行輸出我們會(huì)看到: “1. Phantom Reference: null”.
在上面示例代碼中虛引用PhantomReference的構(gòu)造函數(shù)里, 我傳入了一個(gè)隊(duì)列作為輸入?yún)?shù)。當(dāng)包裹在虛引用實(shí)例中的對(duì)象引用被Java垃圾回收器刪除時(shí),虛引用實(shí)例本身會(huì)自動(dòng)被JVM插入我之前指定到虛引用構(gòu)造函數(shù)輸入?yún)?shù)的那個(gè)隊(duì)列中去。
在System.runFinalization()執(zhí)行之前,phantomRef.isEnqueued()返回false,phantomQueue.poll()返回空。
當(dāng)phantomObj實(shí)例被JVM刪除后, 虛引用PhantomReference本身被加入到隊(duì)列中,并且能夠通過(guò)隊(duì)列提供的API所訪問(wèn):phantomQueue.poll(). 打印輸出的第6行和第7行也說(shuō)明了這一點(diǎn)。
要獲取更多Jerry的原創(chuàng)技術(shù)文章,請(qǐng)關(guān)注公眾號(hào)"汪子熙"或者掃描下面二維碼:
總結(jié)
以上是生活随笔為你收集整理的Java和ABAP中的几种引用类型的分析和比较的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: cpuz如何看cpu体质
- 下一篇: 在ABAP里模拟实现Java Sprin