项目开发中的匿名内部方法总结

简介: 项目开发中的匿名内部方法总结

问题引入

先来看段代码:

import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
public class Test  {
    public static void main(String[] args) {
        Map<String,Object> map  = new HashMap<String, Object>(){{
            put("key1","val1");
            put("key2","val2");
        }};
        String str = new Gson().toJson(map);
        System.out.println("str: "+str);
    }
}

输出:

str: null

初始化HashMap时,这里的双括号到底什么意思代表什么呢?先来看段代码

public class Test {
 public Test() {
  System.out.println("Constructor called:构造器被调用");
 }
 static {
  System.out.println("Static block called:静态块被调用");
 }
 {
  System.out.println("Instance initializer called:实例初始化块被调用");
 }
 public static void main(String[] args) {
  new Test();
  System.out.println("=======================");
  new Test();
 }
}

输出:

 Static block called:静态块被调用
 Instance initializer called:实例初始化被调用
 Constructor called:构造器被调用
 =======================
 Instance initializer called:实例初始化被调用
 Constructor called:构造器被调用

问题分析

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

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

import java.util.HashMap;
class Test$1 extends HashMap // 创建了一个 HashMap 的子类
 {
 Test$1()
 {    // 第二个 {} 中的代码放到了构造方法中去了 
     put("key1","val1");
     put("key2","val2");
 }
 }

问题总结(匿名内部类写法的潜在问题)

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

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

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

new HashMap(map)

这种写法,推而广之,在初始化 ArrayList、Set 的时候都可以这么玩,比如你还可以这么玩:

 List<String> names = new ArrayList<String>() {
 {
 for (int i = 0; i < 10; i++) {
  add("A" + i);
 }
 }
 };
 System.out.println(names.toString()); // [A0, A1, A2, A3, A4, A5, A6, A7, A8, A9]


目录
相关文章
|
监控 数据可视化 前端开发
数据可视化系列-04数据大屏基础知识
数据可视化系列-04数据大屏基础知识
|
监控 Oracle 安全
Oracle数据库用户频繁被锁问题原因排查及解决
由于应用环境下Oracle用户总是频繁被锁,经常不能执行数据库事务操作,严重影响了系统运行效率。通过问题原因分析及排查,发现了原因,在此记录一下。
5104 0
Oracle数据库用户频繁被锁问题原因排查及解决
|
8月前
|
机器学习/深度学习 传感器 自动驾驶
从 2D 到 BEV,LSS 技术如何重塑自动驾驶感知?
LSS(Lift-Splat-Shoot)是将多视角图像转换为BEV表示的经典技术,算法虽然老,但应用依然非常广泛
451 23
从 2D 到 BEV,LSS 技术如何重塑自动驾驶感知?
|
SQL 消息中间件 Java
兼容Trino Connector,扩展Apache Doris数据源接入能力|Lakehouse 使用手册(四)
通过兼容 Connector 插件,Apache Doris 能够支持 Trino/Presto 可对接的所有数据源,而无需改动 Doris 的内核代码。
229 2
兼容Trino Connector,扩展Apache Doris数据源接入能力|Lakehouse 使用手册(四)
|
8月前
|
人工智能 搜索推荐 数据挖掘
销售易CRM:用户体验与实际应用深度分析
销售易CRM是国内领先的客户关系管理系统,以其现代化的界面设计、强大的移动端支持和优质的客户服务著称。系统操作简洁直观,支持个性化定制和多设备访问,确保随时随地办公。移动端功能齐全,提供实时协同工具和离线支持,极大提高工作效率。销售易CRM还注重客户服务,提供快速响应、专业培训和持续优化。实际应用案例显示,该系统帮助中大型企业和成长型企业实现销售流程数字化管理,提升销售效率和客户满意度,是企业数字化转型的理想选择。
|
前端开发 项目管理 开发者
|
Unix Linux Go
go进阶编程:Golang中的文件与文件夹操作指南
本文详细介绍了Golang中文件与文件夹的基本操作,包括读取、写入、创建、删除和遍历等。通过示例代码展示了如何使用`os`和`io/ioutil`包进行文件操作,并强调了错误处理、权限控制和路径问题的重要性。适合初学者和有经验的开发者参考。
208 4
|
Linux
linux命令之cpio
linux命令之cpio
328 2
|
分布式计算 关系型数据库 Serverless
实时数仓 Hologres产品使用合集之如何将ODPS视图表数据导入到Hologres内表
实时数仓Hologres是阿里云推出的一款高性能、实时分析的数据库服务,专为大数据分析和复杂查询场景设计。使用Hologres,企业能够打破传统数据仓库的延迟瓶颈,实现数据到决策的无缝衔接,加速业务创新和响应速度。以下是Hologres产品的一些典型使用场景合集。