新美大的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中的WeakReference

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

  7. java中的泛型的使用与理解

    什么是泛型? 泛型是程序设计语言的一种特性.允许程序员在强类型程序设计语言中编写 体验泛型代码时定义一些可变部份,那些部份在使用前必须作出指明.各种程序设计语言和其编译器.运行环境对泛型的支持均不一样 ...

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

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

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

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

随机推荐

  1. deblurGAN

    -- main.py -- util.py -- data_loader.py -- mode.py -- DeblurGAN.py -- vgg19.py -- layer.py -- vgg19. ...

  2. CXF生成客户端遇到的问题

    一.CXF环境配置路径错误 1.错误现象 在命令行中输入 wsdl2java -v 检查CXF安装是否正确. 出现错误=> ERROR: Unable to find cxf-manifest. ...

  3. [错误记录_C] 还未给指针变量正确赋值的情况下,就使用它的值

    错误的代码: 错误的结果:  错误原因分析: 在使用(1) 将pB,pC的值赋给pA的lchild和rchild时: 还未给指针变量pB和pC赋值,现在pB和pC中存的是个垃圾值 Note: (2)- ...

  4. MySQL数据库学习笔记<一>

    MySQL基本概念以及简单操作   一.MySQL   MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于Oracle 旗下产品.MySQL 是最流行的关系型数据库管理系 ...

  5. android 实现类似微信缓存和即时更新好友头像

    引言 使用微信时我们会发现,首次进入微信的好友列表时,会加载好友头像,但是再次进入时,就不用重新加载了,而且其他页面都不用重新加载,说明微信的好友头像是缓存在本地的,然后好友修改头像后,又会及时的更新 ...

  6. Android Animation 知识点速记备忘思维导图

    备注的大段文本,无法在图片中体现, 思维导图源文件放在附件中.使用 Xmind 8 制作. 附件:AndroidAnimation-xmind.zip

  7. js if语句只写一个参数是什么意思?

    如 var a=0:if(!a){...}; avascript中以下值会被转换为false false undefined null 0 -0 NaN ""

  8. tcp.cc

    ns2-tcp-tcp.cc /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ /* * Copyri ...

  9. January 21 2017 Week 3 Saturday

    Courage is grace under pressure. 勇气就是压力下的优雅. In the face of stress, can you deal with your task smoo ...

  10. Docker Toolbox在window 10 home 下挂载宿主机目录到容器的正确操作

    由于我是window 10 home 而不是 pro版本,只能使用Docker Toolbox,其实docker for window对windows的支持更好,还有GUI,home版本安装Docke ...