新美大的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. SQL Server中的事务日志管理(4/9):简单恢复模式里的日志管理

    当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...

  2. 【Android】记录反编译安卓程序步骤

    主要是为了分析一个 App 里面用到的接口,以后移植 UWP 用. 1.http://jd.benow.ca/ 下载 JD-GUI. 2.https://github.com/pxb1988/dex2 ...

  3. C#一个方法返回多个值

    示例代码: static void Main(string[] args) { //声明 int value; string strOutValue; //调用函数 //函数的参数有两个返回的值 Re ...

  4. myeclipse的实用快捷键

    (1)Ctrl+M切换窗口的大小(2)Ctrl+Q跳到最后一次的编辑处(3)F2当鼠标放在一个标记处出现Tooltip时候按F2则把鼠标移开时Tooltip还会显示即Show Tooltip Desc ...

  5. Python入门版

    一.前言 陆陆续续学习Python已经近半年时间了,感觉到Python的强大之外,也深刻体会到Python的艺术.哲学.曾经的约定,到现在才兑现,其中不乏有很多懈怠,狼狈. Python入门关于Pyt ...

  6. ExtJS4图片验证码的实现

    ExtJS4学习笔记(十)---ExtJS4图片验证码的实现 转自:http://blog.sina.com.cn/s/blog_8d4bbd890100xaxh.html     上多少篇文章,重要 ...

  7. PHP实现上传文件并存进数据库的方法

    本文实例讲述了PHP实现上传文件并存进数据库的方法.分享给大家供大家参考.具体如下: show_add.php文件如下: <?php if(!isset($_REQUEST[''id'']) o ...

  8. C# 通用验证类 支持 WPF,MVC,Winform

    验证方式,   通过继承 IDataErrorInfo接口 和 DataAnnotations 解释标记语言而实现, 为了能在WPF上通用,所了也要继承属性更改通知接口INotifyPropertyC ...

  9. js removeChild 方法

    1. 概述 删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置. 当你遍历一个父节点的子节点并进行删除操作时,要注意,children属性是一个只读属性,并且它在子节点变 ...

  10. 解决Spring MVC @ResponseBody返回html中中文字符串乱码问题

    最近有个应用,通过responsebody返回完整的html页面时出现乱码是异常的问题,因为是通过responsebody返回,所以一开始设置了text/plain的字符集,如下: <mvc:a ...