Java map双括号初始化方式的问题
关于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
}
Java map双括号初始化方式的问题的更多相关文章
- Java:双括号初始化 /匿名内部类初始化法
偶然见到一种初始化方式,感到十分新奇: //新建一个列表并赋初值A.B.C ArrayList<String> list = new ArrayList<String>() { ...
- Java中数组的初始化方式
Java中数组的初始化方式 初始化方式有两种: 1.静态初始化:初始化时由程序猿显式指定每一个数组元素的初始值,由系统指定数组长度 2.动态初始化:初始化时由程序猿仅仅指定数组长度,由系统为数组 ...
- Java Map的正确使用方式
原文:https://www.liaoxuefeng.com/article/1256136507802816 正确使用Map,只需要正确实现hashCode()和equals()就行了吗? 恐怕还不 ...
- Java技巧之双括弧初始化
由于Java语言的集合框架中(collections, 如list, map, set等)没有提供任何简便的语法结构,这使得在建立常量集合时的工作非常繁索.每次建立时我们都要做: 定义一个临时的集合类 ...
- java中Map和List初始化的两种方法
第一种方法(常用方法): //初始化List List<string> list = new ArrayList</string><string>(); list. ...
- java基础-Map的静态初始化以及Map的遍历等.....................
1.map的静态初始化,以及map遍历的几种方法: package com.cy.test; import java.util.HashMap; import java.util.Iterator; ...
- Java Collection - 遍历map的几种方式
作者:zhaoguhong(赵孤鸿) 出处:http://www.cnblogs.com/zhaoguhong/ 本文版权归作者和博客园共有,转载请注明出处 ---------------- 总结 如 ...
- Java遍历Map的3种方式
package test; import java.util.Collection; import java.util.HashMap; import java.util.Map; import ja ...
- java 遍历Map的四种方式
java 遍历Map的四种方式 CreationTime--2018年7月16日16点15分 Author:Marydon 一.迭代key&value 第一种方式:迭代entrySet 1 ...
随机推荐
- 以太网,IP,TCP,UDP数据包分析【转】
原文地址:http://www.cnblogs.com/feitian629/archive/2012/11/16/2774065.html 1.ISO开放系统有以下几层: 7 应用层 6 表示层 5 ...
- 阿里面试的一点感受 阿里ali片式经历和面试题
阿里面试的一点感受 <!-- [废话开始] 百度实习三个月,明天就要离职了,感觉还挺开心的,同事们都很照顾我,Boss也比较欣赏我,我很满足了.掐指一算,这大四其实也没几个月了,同事们都在感叹大 ...
- c运行库、c标准库、windows API的区别和联系
C运行时库函数C运行时库函数是指C语言本身支持的一些基本函数,通常是汇编直接实现的. API函数API函数是操作系统为方便用户设计应用程序而提供的实现特定功能的函数,API函数也是C语言的函数实现的 ...
- React(0.13) 定义一个多选的组件
<!DOCTYPE html> <html> <head> <title>React JS</title> <script src=& ...
- 记录EntityValidationErrors的详细信息
0.一个问题 使用过EF的人相信都会遇到Validation failed for one or more entities. See ‘EntityValidationErrors’这种异常,这是由 ...
- android 点击通知栏返回应用 ,非启动一个新Activity
再使用如下的 Intent 设置: Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ ...
- Swift 值类型/引用类型
1.值类型/引用类型 在 Swift 语言中,所有的类型都可以被分为 "值类型" 或者 "引用类型",可以将其理解为函数参数传递的方式. 值类型表示的是将它传递 ...
- SpringMVC整合Mongodb开发,高级操作
开发环境: 操作系统:windows xpMongodb:2.0.6依 赖 包:Spring3.2.2 + spring-data-mongodb-1.3.0 + Spring-data-1.5 + ...
- Android之内存泄露、内存溢出、内存抖动分析
内存 JAVA是在JVM所虚拟出的内存环境中运行的,内存分为三个区:堆.栈和方法区.栈(stack):是简单的数据结构,程序运行时系统自动分配,使用完毕后自动释放.优点:速度快.堆(heap) ...
- 乙醇的webdriver实用指南java版本
启动浏览器 关闭浏览器 浏览器最大化 设置浏览器大小 访问链接 打印当前页面的title及url 前进和后退 简单的对象定位 定位一组对象 层级定位 操作测试对象 send keys模拟按键输入 处理 ...