IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> 双括号初始化的影响 -> 正文阅读

[开发工具]双括号初始化的影响

简介

我们在开发中偶尔会遇到一些小伙伴使用双括号“{{}}”来进行map或者list的初始化,类似下面示例这样

示例

public class MapTest {
    Map<String,Object> map = new HashMap<String,Object>(){
        {
            put("1","one");
        }
    };
    List<Integer> list = new ArrayList<Integer>(){
        {
            add(1);
            add(2);
        }
    };
}

这样初始化看起来确实挺爽!通俗,简介,易懂
但是越好看的往往越容易踩坑
我们看看编译之后的class文件
在这里插入图片描述
发现除了MapTest.class还有两个class文件。
我们把MapTest$1直接放进IDEA中进行反编译,发现MapTest$1继承了hashmap的

class MapTest$1 extends HashMap<String, Object> {
    MapTest$1(MapTest this$0) {
        this.this$0 = this$0;
        this.put("1", "one");
    }
}

同理MapTest$2也是这样

class MapTest$2 extends ArrayList<Integer> {
    MapTest$2(MapTest this$0) {
        this.this$0 = this$0;
        this.add(1);
        this.add(2);
    }
}

如果工程中大量使用双括号法来进行初始化,就会产生大量的class文件
再使用javap看下内容

javap -v MapTest$1.class
> javap -v MapTest$2.class
Classfile /D:/mysoftware/javabase/target/classes/org/example/MapTest$2.class
  Last modified 2021-11-9; size 657 bytes
  MD5 checksum 0be8f98cffeb87ca4a8fa953e4ef7b95
  Compiled from "MapTest.java"
class org.example.MapTest$2 extends java.util.ArrayList<java.lang.Integer>
  minor version: 0
  major version: 52
  flags: ACC_SUPER
Constant pool:
   #1 = Fieldref           #5.#23         // org/example/MapTest$2.this$0:Lorg/example/MapTest;
   #2 = Methodref          #6.#24         // java/util/ArrayList."<init>":()V
   #3 = Methodref          #25.#26        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #4 = Methodref          #5.#27         // org/example/MapTest$2.add:(Ljava/lang/Object;)Z
   #5 = Class              #28            // org/example/MapTest$2
   #6 = Class              #29            // java/util/ArrayList
   #7 = Utf8               this$0
   #8 = Utf8               Lorg/example/MapTest;
   #9 = Utf8               <init>
  #10 = Utf8               (Lorg/example/MapTest;)V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               LocalVariableTable
  #14 = Utf8               this
  #15 = Utf8               InnerClasses
  #16 = Utf8               Lorg/example/MapTest$2;
  #17 = Utf8               Signature
  #18 = Utf8               Ljava/util/ArrayList<Ljava/lang/Integer;>;
  #19 = Utf8               SourceFile
  #20 = Utf8               MapTest.java
  #21 = Utf8               EnclosingMethod
  #22 = Class              #30            // org/example/MapTest
  #23 = NameAndType        #7:#8          // this$0:Lorg/example/MapTest;
  #24 = NameAndType        #9:#31         // "<init>":()V
  #25 = Class              #32            // java/lang/Integer
  #26 = NameAndType        #33:#34        // valueOf:(I)Ljava/lang/Integer;
  #27 = NameAndType        #35:#36        // add:(Ljava/lang/Object;)Z
  #28 = Utf8               org/example/MapTest$2
  #29 = Utf8               java/util/ArrayList
  #30 = Utf8               org/example/MapTest
  #31 = Utf8               ()V
  #32 = Utf8               java/lang/Integer
  #33 = Utf8               valueOf
  #34 = Utf8               (I)Ljava/lang/Integer;
  #35 = Utf8               add
  #36 = Utf8               (Ljava/lang/Object;)Z
{
  final org.example.MapTest this$0;     //持有外部类的引用
    descriptor: Lorg/example/MapTest;
    flags: ACC_FINAL, ACC_SYNTHETIC

  org.example.MapTest$2(org.example.MapTest);
    descriptor: (Lorg/example/MapTest;)V
    flags:
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #1                  // Field this$0:Lorg/example/MapTest;
         5: aload_0
         6: invokespecial #2                  // Method java/util/ArrayList."<init>":()V
         9: aload_0
        10: iconst_1
        11: invokestatic  #3                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        14: invokevirtual #4                  // Method add:(Ljava/lang/Object;)Z
        17: pop
        18: aload_0
        19: iconst_2
        20: invokestatic  #3                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        23: invokevirtual #4                  // Method add:(Ljava/lang/Object;)Z
        26: pop
        27: return
      LineNumberTable:
        line 14: 0
        line 16: 9
        line 17: 18
        line 18: 27
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      28     0  this   Lorg/example/MapTest$2;
            0      28     1 this$0   Lorg/example/MapTest;
}
Signature: #18                          // Ljava/util/ArrayList<Ljava/lang/Integer;>;
SourceFile: "MapTest.java"
EnclosingMethod: #22.#0                 // org.example.MapTest
InnerClasses:
     #5; //class org/example/MapTest$2

看到了这里,发现内部类持有外部类的引用,并且在构造块中进行初始化
如果我们这样

public class MapTest {
    private Map<String,Object> get(){
        return new HashMap<String,Object>(){
            {
                put("1","one");
                put("2","two");
                put("3","tree");
            }
        };
    }
    public static void main(String[] args) {
        System.out.println(new MapTest().get().getClass().getName());
    }
}
"C:\Program Files\Java\jdk1.8.0_121\bin\java.exe" -Dvisualvm.id=1006217305728700 "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2020.1.3\lib\idea_rt.jar=61834:D:\Program Files\JetBrains\IntelliJ IDEA 2020.1.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_121\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\rt.jar;D:\mysoftware\javabase\target\classes" org.example.MapTest
org.example.MapTest$3

Process finished with exit code 0

可以看到返回的是内部类,如果此内部类被其他类所使用,那么,根据GC的可达性分析算法,外部类是没有办法被回收的,这便会产生内存泄漏问题

总结

如果工程中大量使用双括号法来进行初始化,就会产生大量的class文件
可能会造成内存泄漏

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2021-11-11 12:55:00  更:2021-11-11 12:55:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 20:41:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码