EffectiveJava 1創建和銷燬對象 6消除過期的對象引用

1    重點關注

1.1    通用方法避免過期對象的應用

消除過期引用的最好方法是讓包含該引用的變量結束其生命週期。

如果使用最緊湊作用域範圍定義每一個變量,這種情形自然而然的發生

 

1.2    消除過期對象的使用場景

a    棧的pop,需要我們手動清空,因爲棧類自己管理內存

b    隨着時間推移,過期緩存可以使用後臺線程來完成消除(可以用定時器);  如果緩存之外存在某項鍵的外部引用,也可以用WeakHashMap

c    監聽器和其他回調(如果使用HashMap的話),可以使用弱引用參考3.3,相關案例可以參考https://blog.csdn.net/weixin_36410904/article/details/114160943

 

 

2    課程內容

2.1    數組屬於棧還是隊列?棧和隊列的區別

答:靜態數組,List存儲於棧上

棧是先進後出,有底的瓶子

隊列是先進先出,無底的瓶子

有了這個基礎,再看3.1

 

棧:有編譯器自動分配和釋放,存放函數的參數、局部變量、臨時變量、函數返回地址等;

 

2.2    實時設置數組的大小

見3.1的 ensurCapacity 方法

 

2.3    重要關注

參見1

 

3    代碼演練

3.1    棧的彈出未消除過期對象(反例)

棧:

package com.ddwei.test.core.chapter6.demo1;

import java.util.Arrays;
import java.util.EmptyStackException;

public class Stack {

    private Object[] elements;
    private static final int DEFALUT_INITIAL_CAPACITY = 4;
    private int size = 0;

    public Stack(){
        elements = new Object[DEFALUT_INITIAL_CAPACITY ];
    }

    /**
     * 棧移入元素
     * @author weidoudou
     * @date 2022/6/27 12:52
     * @param obj 請添加參數描述
     * @return void
     **/
    public void push(Object obj){
        //
       ensurCapacity();
       elements[size++] = obj;
    }

    /**
     * 棧移除元素
     * @author weidoudou
     * @date 2022/6/27 12:51
     * @param
     * @return java.lang.Object
     **/
    public Object pop(){
        if(size == 0){
            throw new EmptyStackException();
        }
        return elements[--size];
    }

    /**
     * 預先設置數組的大小,每次數組元素不夠的時候,進行擴充兩倍
     * @author weidoudou
     * @date 2022/6/27 12:49
     * @param
     * @return void
     **/
    public void ensurCapacity(){
        if(elements.length == size){
            elements = Arrays.copyOf(elements,2*size+1);
        }
    }


}

 

 

測試類:

package com.ddwei.test.core.chapter6.demo1;

public class StackTest {

    public static void main(String[] args) {
        Stack stack = new Stack();
        stack.push("0");
        stack.push("1");
        stack.push("2");
        stack.push("3");
        stack.push("4");
        stack.pop();
    }

}

 

 

3.2    棧的彈出消除過期對象(正例)

棧:(着重看   elements[size] = null;)

package com.ddwei.test.core.chapter6.demo2;

import java.util.Arrays;
import java.util.EmptyStackException;

public class Stack2 {

    private Object[] elements;
    private static final int DEFALUT_INITIAL_CAPACITY = 16;
    private int size = 0;

    public Stack2(){
        elements = new Object[DEFALUT_INITIAL_CAPACITY ];
    }

    /**
     * 棧移入元素
     * @author weidoudou
     * @date 2022/6/27 12:52
     * @param obj 請添加參數描述
     * @return void
     **/
    public void push(Object obj){
        //
       ensurCapacity();
       elements[size++] = obj;
    }

    /**
     * 棧移除元素
     * @author weidoudou
     * @date 2022/6/27 12:51
     * @param
     * @return java.lang.Object
     **/
    public Object pop(){
        if(size == 0){
            throw new EmptyStackException();
        }
        Object result = elements[--size];
        elements[size] = null;
        return result;
    }

    /**
     * 預先設置數組的大小,每次數組元素不夠的時候,進行擴充兩倍
     * @author weidoudou
     * @date 2022/6/27 12:49
     * @param
     * @return void
     **/
    public void ensurCapacity(){
        if(elements.length == size){
            elements = Arrays.copyOf(elements,2*size+1);
        }
    }


}

 

測試類:

package com.ddwei.test.core.chapter6.demo2;

import com.ddwei.test.core.chapter6.demo1.Stack;

public class StackTest2 {

    public static void main(String[] args) {
        Stack2 stack = new Stack2();
        stack.push("0");
        stack.push("1");
        stack.push("2");
        stack.push("3");
        stack.push("4");
        stack.pop();
    }

}

 

 

3.3    弱引用demo

demo

package com.ddwei.test.core.chapter6.demo3;

import java.lang.ref.WeakReference;

public class App {

    public static WeakReference<String> weakReference1;

    public static void main(String[] args) {

        test1();
        //test1外部,hello對象作用域結束,沒有強引用指向"value"了。只有一個弱引用指向"value"
        System.out.println("未進行gc時,只有弱引用指向value內存區域:" + weakReference1.get());

        //此時gc時會回收弱引用
        System.gc();
        
        //此時輸出都爲nuill
        System.out.println("進行gc時,只有弱引用指向value內存區域:" + weakReference1.get());

    }

    public static void test1() {
        //hello對象強引用"value"
        String hello = new String("value");

        //weakReference1對象弱引用指向"value"
        weakReference1 = new WeakReference<>(hello);

        //在test1內部調用gc,此時gc不會回收弱引用,因爲hello對象強引用"value"
        System.gc();
        System.out.println("進行gc時,強引用與弱引用同時指向value內存區域:" + weakReference1.get());

    }

}

 

打印日誌

進行gc時,強引用與弱引用同時指向value內存區域:value
未進行gc時,只有弱引用指向value內存區域:value
進行gc時,只有弱引用指向value內存區域:null

Process finished with exit code 0

 

3.4    List的Remove方法不需要消除過期對象

demo

package com.ddwei.test.core.chapter6.demo4;

import java.util.ArrayList;
import java.util.List;

public class ListTest {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.remove("aaa");
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章