新美大的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的理解的更多相关文章

  1. 【转】Java中关于WeakReference和WeakHashMap的理解

    新美大的10月11日的笔试中有一道选择题,让选择函数返回结果,代码如下: private static String test(){ String a = new String("a&quo ...

  2. 关于Java中语句符号及格式的理解

    关于Java中语句符号及格式的理解 这篇文章是撰写的第一篇文章,在此作一下博主是一名在读的工科研究生,种种原因,研二开始决定转行从事程序员工作.开始的自学之路并不算非常顺畅,也走了一点弯路,但一直都坚 ...

  3. Java中关于static语句块的理解

    Java中关于static语句块的理解 一.static块会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法. 实例一 public class A{ String name ...

  4. Java中常用的设计模式代码与理解

    Java中常用的设计模式代码与理解 一.单例模式 1.饿汉式 (太饿了,类加载的时候就创建实例) /** * 饿汉式单例模式 */ public class HungrySingleInstance ...

  5. Java中的 WeakReference 和 SoftReference

    我们知道Java语言中没有指针,取而代之的是引用reference.Java中的引用又可以分为四种:强引用,弱引用(WeakReference),软引用(SoftReference),虚引用(Phan ...

  6. java中set和get方法的理解

    对于JAVA初学者来说,set和get这两个方法似乎已经很熟悉了,这两个方法是JAVA变成中的基本用法,也是出现频率相当高的两个方法. 为了让JAVA初学者能更好的理解这两个方法的使用和意义,今天笔者 ...

  7. 谈谈java中的WeakReference

    Java语言中为对象的引用分为了四个级别,分别为 强引用 .软引用.弱引用.虚引用. 本文只针对java中的弱引用进行一些分析,如有出入还请多指正. 在分析弱引用之前,先阐述一个概念:什么是对象可到达 ...

  8. Java中==与equals的区别及理解

    区别: "==" 比较的是两个引用在内存中指向的是不是同一对象(即同一内存空间),也就是说在内存空间中的存储位置是否一致. 如果两个对象的引用相同时(指向同一对象时)," ...

  9. Java中char和String 的深入理解 - 字符编码

    开篇 https://blog.csdn.net/weixin_37703598/article/details/80679376 我们并不是在写代码,我们只是将自己的思想通过代码表达出来! 1 将思 ...

随机推荐

  1. 浅谈DOM性能考虑

    浅谈DOM性能考虑 很多人都会忽视脚本对Web应用整体性能的影响.为保证应用的流畅运行,在为文档编写和应用脚本时,需要注意一些问题.一.尽量减少访问DOM和尽量减少标记    访问DOM的方式对脚本性 ...

  2. UIApplication和delegate代理

    所有的移动操作系统都有个致命的缺点:app很容易受到打扰,比如一个来电或者锁屏都会导致app进入后台甚至被终止 还有很多其他类似的情况会导致app受到干扰,在app受到干扰时,会产生一些系统事件,这是 ...

  3. DES算法详解

    本文主要介绍了DES算法的步骤,包括IP置换.密钥置换.E扩展置换.S盒代替.P盒置换和末置换. 1.DES算法简介 DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准. DES是一个分组 ...

  4. mysql创建每月执行一次的event

    DELIMITER $$ CREATE /*[DEFINER = { user | CURRENT_USER }]*/ EVENT `dev_sp2p6`.`e_test1` ON SCHEDULEE ...

  5. MVC知识点02

    MVC基础知识详情 1:在MVC中如果要从前台页面(.aspx)获取参数,只需要将其两个页面的参数设置成一样的,这样子MVC中的机制就会自动的将参数的值传到方法中. 2:在MVC中的方法要是两个都是相 ...

  6. UnityShader快速上手指南(三)

    简介 这一篇还是一些基本的shader操作:裁剪.透明和法向量的应用 (纠结了很久写不写这些,因为代码很简单,主要是些概念上的东西) 先来看下大概的效果图:(从左到右依次是裁剪,透明,加了法向量的透明 ...

  7. 2015年最热门前端框架React 入门实例教程

    现在最热门的前端框架,毫无疑问是 React . 上周,基于 React 的 React Native 发布,结果一天之内,就获得了 5000 颗星,受瞩目程度可见一斑. React 起源于 Face ...

  8. WPF学习之深入浅出话命令

    WPF为我们准备了完善的命令系统,你可能会问:"有了路由事件为什么还需要命令系统呢?".事件的作用是发布.传播一些消息,消息传达到了接收者,事件的指令也就算完成了,至于如何响应事件 ...

  9. C#递归题目代码

    一列数的规则如下: 1.1.2.3.5.8.13.21.34...... 求第30位数是多少, 用递归算法实现. 代码: public class MainClass { public static ...

  10. nginx跨域处理

    http://www.nginx.cn/nginx-download nginx.conf配置 if ($request_method = ‘OPTIONS’) {         add_heade ...