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

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

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 
}

ref:http://www.iteye.com/topic/418542

     http://www.evget.com/zh-CN/Info/catalog/12289.html     

### JavaMap初始化方法 #### 新建Map对象并手动填充数据 通过创建`HashMap<String, String>`实例来构建一个名为`myMap`的地图,并利用静态代码块中的`put()`函数向其中加入键值对[^1]。 ```java public class Demo { private static final Map<String, String> myMap = new HashMap<>(); static{ myMap.put("key1", "value1"); myMap.put("key2", "value2"); } } ``` #### 使用括号语法(匿名内部类) 这种方式是在定义的同时完成赋值操作,适用于不需要对外暴露修改权限的情况。它基于匿名内部类实现,在大括号内可以直接调用`put`方法[^4]。 ```java Map<String, Integer> map = new HashMap<>() {{ put("one", 1); put("two", 2); }}; ``` #### 利用Java 9引入的简化构造器 自JDK 9起支持更简洁的方式来声明不可变映射表——即那些一旦被设定就不能再更改其内容的数据结构。这不仅使代码更加紧凑易读,而且还能提高程序的安全性和性能。 ```java import java.util.Map; // 创建带有两个条目的只读视图 Map<String, Long> readOnlyMap = Map.of( "apple", 3L, "banana", 2L); // 如果需要更多元素,则可采用ofEntries()形式 Map<String, Long> largerReadOnlyMap = Map.ofEntries( Map.entry("apple", 3L), Map.entry("banana", 2L), Map.entry("orange", 5L)); ``` #### 借助第三方库Guava提供的工具类 除了标准API外,Google Guava等外部依赖项也提供了便捷的方法用于快速建立哈希表或其他类型的关联数组。这些额外的功能往往能够满足特定场景下的需求。 ```java import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; // 构造ImmutableMap ImmutableMap<String, Integer> immutableExample = ImmutableMap.<String, Integer>builder() .put("first", 10) .put("second", 20).build(); // 或者使用Maps.newLinkedHashMap()等其他实用工厂方法 Map<String, Double> linkedHashMapExample = Maps.newLinkedHashMap(); linkedHashMapExample.put("pi", Math.PI); linkedHashMapExample.put("euler", Math.E); ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值