博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java map双括号初始化方式的问题
阅读量:6835 次
发布时间:2019-06-26

本文共 1275 字,大约阅读时间需要 4 分钟。

关于Java双括号的初始化凡是确实很方便,特别是在常量文件中,无可替代。如下所示:

Map map = new HashMap() {

  {
  put("Name", "Unmi");
  put("QQ", "1125535");
  }
};

好处很明显就是一目了然。这里来罗列下此种方法的坏处,如果这个对象要串行化,可能会导致串行化失败。

1.此种方式是匿名内部类的声明方式(不懂的下文有详尽解释),所以引用中持有着外部类的引用。所以当时串行化这个集合时外部类也会被不知不觉的串行化,当外部类没有实现serialize接口时,就会报错。

2.上例中,其实是声明了一个继承自Hashset的子类。然而有些串行化方法,例如要通过Gson串行化为json,或者要串行化为xml时,类库中提供的方式,是无法串行化Hashset或者HashMap的子类的,从而导致串行化失败。解决办法:重新初始化为一个Hashset对象:

new HashMap(map);

这样就可以正常初始化了。

双括号写法的原理:

第一层括弧 实际是定义了一个内部匿名类 (Anonymous Inner Class),第二层括弧 实际上是一个实例初始化块 (instance initializer block),这个块在内部匿名类构造时被执行。这个块之所以被叫做“实例初始化块”是因为它们被定义在了一个类的实例范围内。

上面代码如果是写在 TestDoubleBrace 类中,编译后你会看到会生成 TestDoubleBrace$1.class 文件,反编译该文件内容是:

final class com.unmi.TestDoubleBrace$1 extends java.util.HashMap{ //创建了一个 HashMap 的子类 TestDoubleBracke$1

  com.unmi.TestDoubleBrace$1();

Code:

  0: aload_0
  1: invokespecial #8; //Method java/util/HashMap."":()V //{} 中的代码放到了构造方法中去了
  4: aload_0
  5: ldc #10; //String Name
  7: ldc #12; //String Unmi
  9: invokevirtual #14; //Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
  12: pop
  13: aload_0
  14: ldc #18; //String QQ
  16: ldc #20; //String 1125535
  18: invokevirtual #14; //Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
  21: pop
  22: return
}

转载地址:http://shqkl.baihongyu.com/

你可能感兴趣的文章
elixir官方入门教程 模式匹配
查看>>
IE下使用jQuery重置iframe地址时内存泄露问题解决办法
查看>>
使用运行时动态创建属性
查看>>
MySQL编译安装及主从配置
查看>>
web 关于跳转
查看>>
如何定义一个不能被继承的类
查看>>
给字体加粗
查看>>
python 第一课
查看>>
微信搜索谁把你删除了
查看>>
1482奖学金
查看>>
虚拟化数据中心服务器硬件配置建议
查看>>
CentOS6.4 添加播放×××
查看>>
支付宝移动支付文档url
查看>>
自动化运维之CentOS7下PXE+Kickstart+DHCP+TFTP+HTTP无人值守安装系统
查看>>
SFB 项目经验-51-某上市企业2千人Exchange 2013升级2016高可用之伤01
查看>>
【迁移2018-04-12 10:46:11】BeanCopier之MapStruct(一)
查看>>
编程的智慧
查看>>
spring 项目中的一个异常
查看>>
16个Linux服务器监控命令
查看>>
我的友情链接
查看>>