java referencemap_Java中关于WeakReference和WeakHashMap的理解

本文通过一道Java笔试题深入解析了WeakReference和WeakHashMap的工作原理及其在垃圾回收机制中的角色。在题目中,由于 WeakReference 的对象在失去强引用后会被GC回收,导致在WeakHashMap中无法获取到有效的键,从而引发异常。最后,文章还介绍了Java异常处理中try-catch-finally的执行流程,并分析了代码执行的结果。
摘要由CSDN通过智能技术生成

新美大的10月11日的笔试中有一道选择题,让选择函数返回结果,代码如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 private static String test(){

2 String a = new String("a");

3 WeakReference b = new WeakReference(a);

4 WeakHashMap weakMap = new WeakHashMap();

5 weakMap.put(b.get(), 1);

6 a = null;

7 System.gc();

8 String c = "";

9 try{

10 c = b.get().replace("a", "b");

11 return c;

12 }catch(Exception e){

13 c = "c";

14 return c;

15 }finally{

16 c += "d";

17 return c + "e";

18 }

19 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

运行结果是“cde”。

该题关键在考察WeakReference和WeakHashMap的理解。

先说下一点Java GC内容

在Java里, 当一个对象object被创建时,它被放在Heap里。当GC运行的时候,如果发现没有任何引用指向object,object就会被回收以腾出内存空间。或者换句话说,一个对象被回收,必须满足两个条件:1)没有任何引用指向它 2)GC被运行.

WeakReference

当一个对象仅仅被weak reference(弱引用)指向, 而没有任何其他strong reference(强引用)指向的时候, 如果GC运行, 那么这个对象就会被回收。weak reference的语法是:

WeakReference weakref = new WeakReference();

当要获得WeakReference的object时, 首先需要判断它是否已经被GC回收,若被收回,则下列返回值为空:

weakref.get();

所以在上述代码中,经过a=null; System.gc()后,在WeakReference b = new WeakReference(a);中a为空已经被系统收回了,而b已经没有强引用指向了,所以b也被系统GC收回了。所以当代码运行到c = b.get().replace("a", "b");时,由于b.get()为null,会抛出异常。

WeakHashMap

WeakHashMap其实和HashMap用法类似,它们之间唯一的区别就是:HashMap中的key保存的是实际对象的强引用,因此只要对象不被销毁,即该key所对应的key-value都不会被垃圾回收机制回收。但是WeakHashMap保存的实际对象是弱引用,这意味着只要该对象没有被强对象引用就有可能会被垃圾回收机制回收对应的Key-value。示例如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png

import java.util.WeakHashMap;

public class WeakHashMapTest {

public static void main(String[] args) {

WeakHashMap w= new WeakHashMap();

//三个key-value中的key 都是匿名对象,没有强引用指向该实际对象

w.put(new String("语文"),new String("优秀"));

w.put(new String("数学"), new String("及格"));

w.put(new String("英语"), new String("中等"));

//增加一个字符串的强引用

w.put("java", new String("特别优秀"));

System.out.println(w);

//通知垃圾回收机制来进行回收

System.gc();

System.runFinalization();

//再次输出w

System.out.println("第二次输出:"+w);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

输出结果:{java=特别优秀, 数学=及格, 英语=中等, 语文=优秀}

第二次输出w:{java=特别优秀}

所以在最开始的代码中WeakHashMap weakMap = new WeakHashMap(); weakMap没有强引用指引,所以在执行System.gc()后weakMap被系统GC收回。

打印出代码中的变量

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 private static String test(){

2 String a = new String("a");

3 //System.out.println(a);

4 WeakReference b = new WeakReference(a);

5 //System.out.println(b.get());

6 WeakHashMap weakMap = new WeakHashMap();

7 weakMap.put(b.get(), 1);

8 a = null;

9 System.out.println("GC前b.get():"+b.get());

10 System.out.println("GC前weakMap:"+weakMap);

11 System.gc();

12 System.out.println("GC后"+b.get());

13 System.out.println("GC后"+weakMap);

14 String c = "";

15 try{

16 c = b.get().replace("a", "b");

17 System.out.println("C:"+c);

18 return c;

19 }catch(Exception e){

20 c = "c";

21 System.out.println("Exception");

22 return c;

23 }finally{

24 c += "d";

25 return c + "e";

26 }

27 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

运行后结果为:

48304ba5e6f9fe08f3fa1abda7d326ab.png

GC前b.get():a

GC前weakMap:{a=1}

GC后null

GC后{}

Exception

cde

48304ba5e6f9fe08f3fa1abda7d326ab.png

可见,在System.gc()前后的WeakReference和WeakHashMap的变化。

Java中异常处理中try,catch,finally的关系

java 的异常处理中,

在不抛出异常的情况下,程序执行完 try 里面的代码块之后,该方法并不会立即结束,而是继续试图去寻找该方法有没有 finally 的代码块,

如果没有 finally 代码块,整个方法在执行完 try 代码块后返回相应的值来结束整个方法;

如果有 finally 代码块,此时程序执行到 try 代码块里的 return 语句之时并不会立即执行 return(如果return后是语句或者函数,eg:return b+=10; or return functionA();,先执行return后的语句或者函数),而再去执行 finally 代码块里的代码,

若 finally 代码块里没有 return 或没有能够终止程序的代码,程序将在执行完 finally 代码块代码之后再返回 try 代码块执行 return 语句来结束整个方法;

若 finally 代码块里有 return 或含有能够终止程序的代码,方法将在执行完 finally 之后被结束,不再跳回 try 代码块执行 return。

在抛出异常的情况下,原理也是和上面的一样的,你把上面说到的 try 换成 catch 去理解就 OK 了。

现在分析上述代码:

System.gc()后b.get()和weakMap均为null

try中抛出异常,在catch中捕获异常

执行c = "c",执行到return c,但是并不立即return,执行finally

执行 c +="d"; return c + "e",finally代码块中有return语句就不会返回catch中执行return了。

所以最终结果是return "cde"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值