1    重点关注

1.1    通用方法避免过期对象的应用

消除过期引用的最好方法是让包含该引用的变量结束其生命周期。

如果使用最紧凑作用域范围定义每一个变量,这种情形自然而然的发生

 

1.2    消除过期对象的使用场景

a    栈的pop,需要我们手动清空,因为栈类自己管理内存

b    随着时间推移,过期缓存可以使用后台线程来完成消除(可以用定时器);  如果缓存之外存在某项键的外部引用,也可以用WeakHashMap

c    监听器和其他回调(如果使用HashMap的话),可以使用弱引用参考3.3,相关案例可以参考

 

 

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");
    }

}