Java map双括号初始化方式的问题

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

Map map = new HashMap() { 
  { 
  put("Name", "Unmi"); 
  put("QQ", "1125535"); 
  } 
};linux

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

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

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

new HashMap(map);orm

这样就能够正常初始化了。xml

双括号写法的原理:htm

第一层括弧 实际是定义了一个内部匿名类 (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 
}

编写高质量代码 改善Java程序的151个建议 PDF高清完整版 http://www.linuxidc.com/Linux/2014-06/103388.htm

Java 8简明教程 http://www.linuxidc.com/Linux/2014-03/98754.htm

Java对象初始化顺序的简单验证 http://www.linuxidc.com/Linux/2014-02/96220.htm

Java对象值传递和对象传递的总结 http://www.linuxidc.com/Linux/2012-12/76692.htm

Java对象序列化ObjectOutputStream和ObjectInputStream示例 http://www.linuxidc.com/Linux/2012-08/68360.htm

本文永久更新连接地址http://www.linuxidc.com/Linux/2014-06/103535.htm

相关文章
相关标签/搜索