Java中关于WeakReference和WeakHashMap的理解
新美大的10月11日的笔试中有一道选择题,让选择函数返回结果,代码如下:
private static String test(){
String a = new String("a");
WeakReference<String> b = new WeakReference<String>(a);
WeakHashMap<String, Integer> weakMap = new WeakHashMap<String, Integer>();
weakMap.put(b.get(), 1);
a = null;
System.gc();
String c = "";
try{
c = b.get().replace("a", "b");
return c;
}catch(Exception e){
c = "c";
return c;
}finally{
c += "d";
return c + "e";
}
}
运行结果是“cde”。
该题关键在考察WeakReference和WeakHashMap的理解。
先说下一点Java GC内容
在Java里, 当一个对象object被创建时,它被放在Heap里。当GC运行的时候,如果发现没有任何引用指向object,object就会被回收以腾出内存空间。或者换句话说,一个对象被回收,必须满足两个条件:1)没有任何引用指向它 2)GC被运行.
WeakReference
当一个对象仅仅被weak reference(弱引用)指向, 而没有任何其他strong reference(强引用)指向的时候, 如果GC运行, 那么这个对象就会被回收。weak reference的语法是:
WeakReference<T> weakref = new WeakReference<T>();
当要获得WeakReference的object时, 首先需要判断它是否已经被GC回收,若被收回,则下列返回值为空:
weakref.get();
所以在上述代码中,经过a=null; System.gc()后,在WeakReference<String> b = new WeakReference<String>(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。示例如下:
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);
}
}
输出结果:{java=特别优秀, 数学=及格, 英语=中等, 语文=优秀}
第二次输出w:{java=特别优秀}
所以在最开始的代码中WeakHashMap<String, Integer> weakMap = new WeakHashMap<String, Integer>(); weakMap没有强引用指引,所以在执行System.gc()后weakMap被系统GC收回。
打印出代码中的变量
private static String test(){
String a = new String("a");
//System.out.println(a);
WeakReference<String> b = new WeakReference<String>(a);
//System.out.println(b.get());
WeakHashMap<String, Integer> weakMap = new WeakHashMap<String, Integer>();
weakMap.put(b.get(), 1);
a = null;
System.out.println("GC前b.get():"+b.get());
System.out.println("GC前weakMap:"+weakMap);
System.gc();
System.out.println("GC后"+b.get());
System.out.println("GC后"+weakMap);
String c = "";
try{
c = b.get().replace("a", "b");
System.out.println("C:"+c);
return c;
}catch(Exception e){
c = "c";
System.out.println("Exception");
return c;
}finally{
c += "d";
return c + "e";
}
}
运行后结果为:
GC前b.get():a
GC前weakMap:{a=1}
GC后null
GC后{}
Exception
cde
可见,在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"
Java中关于WeakReference和WeakHashMap的理解的更多相关文章
- 【转】Java中关于WeakReference和WeakHashMap的理解
新美大的10月11日的笔试中有一道选择题,让选择函数返回结果,代码如下: private static String test(){ String a = new String("a&quo ...
- 关于Java中语句符号及格式的理解
关于Java中语句符号及格式的理解 这篇文章是撰写的第一篇文章,在此作一下博主是一名在读的工科研究生,种种原因,研二开始决定转行从事程序员工作.开始的自学之路并不算非常顺畅,也走了一点弯路,但一直都坚 ...
- Java中关于static语句块的理解
Java中关于static语句块的理解 一.static块会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法. 实例一 public class A{ String name ...
- Java中常用的设计模式代码与理解
Java中常用的设计模式代码与理解 一.单例模式 1.饿汉式 (太饿了,类加载的时候就创建实例) /** * 饿汉式单例模式 */ public class HungrySingleInstance ...
- Java中的 WeakReference 和 SoftReference
我们知道Java语言中没有指针,取而代之的是引用reference.Java中的引用又可以分为四种:强引用,弱引用(WeakReference),软引用(SoftReference),虚引用(Phan ...
- java中set和get方法的理解
对于JAVA初学者来说,set和get这两个方法似乎已经很熟悉了,这两个方法是JAVA变成中的基本用法,也是出现频率相当高的两个方法. 为了让JAVA初学者能更好的理解这两个方法的使用和意义,今天笔者 ...
- 谈谈java中的WeakReference
Java语言中为对象的引用分为了四个级别,分别为 强引用 .软引用.弱引用.虚引用. 本文只针对java中的弱引用进行一些分析,如有出入还请多指正. 在分析弱引用之前,先阐述一个概念:什么是对象可到达 ...
- Java中==与equals的区别及理解
区别: "==" 比较的是两个引用在内存中指向的是不是同一对象(即同一内存空间),也就是说在内存空间中的存储位置是否一致. 如果两个对象的引用相同时(指向同一对象时)," ...
- Java中char和String 的深入理解 - 字符编码
开篇 https://blog.csdn.net/weixin_37703598/article/details/80679376 我们并不是在写代码,我们只是将自己的思想通过代码表达出来! 1 将思 ...
随机推荐
- Android 学习笔记多媒体技术之 AsyncTask+实现音频播放...
PS:今天搞了一下如何实现音频播放...结果被坑了,看书上写的代码是挺简单的,但是有个函数就是死活没看懂,这真是受不了...最后才弄明白,原来是一个实现异步任务的一个类...这个类使用java.uti ...
- jquery判断radioButton是否被选中
so easy HTML: <input type='radio' style='width:20px' id='other' name='projectType' value='其他' /&g ...
- lnmp_auto:自动化安装lnmp环境脚本
朋友找我在一台机器上帮忙安装下discuz.想着搭建过好几次的lnmp了,但是还没有使用过"一键安装"的自动化脚本,去网上有搜索出来,但是运行的时候发现用root运行别人的脚本还是 ...
- IOS7中自动计算label的宽度和高度的方法
#import "ViewController.h" @implementation ViewController - (void)viewDidLoad { [super vie ...
- [ORM] Entity Framework(2) CodeFirst进阶
在上一节中,实现了CodeFirst快速入门.但是很多与数据库的细节还无法自定义.以及使用EF过程中,需要注意的事项. 在本节中,会涉及到以下 EF中的连接字符串 EF的对象状态 延迟加载,为什么需要 ...
- 重构第11天 使用策略代替Switch(Switch to Strategy)
理解:策略就是平常设计模式中所说的策略模式.因为当你有一个庞大的switch方法的时候,每一次新加一个条件,都要去修改这个方法,这样耦合性太高,不易维护也不易扩展.这样我们就可以使用策略的设计模式,使 ...
- 加密–RSA前端与后台的加密&解密
1. 前言 本问是根据网上很多文章的总结得到的. 2. 介绍 RSA加密算法是一种非对称加密算法. 对极大整数做因数分解的难度决定了RSA算法的可靠性.换言之,对一极大整数做因数分解愈困难,RSA算法 ...
- php实现的IMEI限制的短信验证码发送类
php实现的IMEI限制的短信验证码发送类 <?php class Api_Sms{ const EXPIRE_SEC = 1800; // 过期时间间隔 const RESEND_SEC = ...
- #define lowbit(x) ((x)&(-x))原理详解
#define lowbit(x) ((x)&(-x)) 也可以写成如下形式: int Lowbit(x) { return x&(-x); } 例如: 1> x = 1: 十进 ...
- SpringMVC中出现" 400 Bad Request "错误(用@ResponseBody处理ajax传过来的json数据转成bean)的解决方法
最近angularjs post到后台 400一头雾水 没有任何错误. 最后发现好文,感谢作者 SpringMVC中出现" 400 Bad Request "错误(用@Respon ...