栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

双括号初始化的影响

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

双括号初始化的影响

简介

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

示例
public class MapTest {
    Map map = new HashMap(){
        {
            put("1","one");
        }
    };
    List list = new ArrayList(){
        {
            add(1);
            add(2);
        }
    };
}

这样初始化看起来确实挺爽!通俗,简介,易懂
但是越好看的往往越容易踩坑
我们看看编译之后的class文件

发现除了MapTest.class还有两个class文件。
我们把MapTest$1直接放进IDEA中进行反编译,发现MapTest$1继承了hashmap的

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

同理MapTest$2也是这样

class MapTest$2 extends ArrayList {
    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
  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."":()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               
  #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;
  #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         // "":()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."":()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;
SourceFile: "MapTest.java"
EnclosingMethod: #22.#0                 // org.example.MapTest
InnerClasses:
     #5; //class org/example/MapTest$2

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

public class MapTest {
    private Map get(){
        return new HashMap(){
            {
                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 FilesJavajdk1.8.0_121binjava.exe" -Dvisualvm.id=1006217305728700 "-javaagent:D:Program FilesJetBrainsIntelliJ IDEA 2020.1.3libidea_rt.jar=61834:D:Program FilesJetBrainsIntelliJ IDEA 2020.1.3bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_121jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_121jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_121jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_121jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_121jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_121jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_121jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_121jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_121jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_121jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_121jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_121jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_121jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_121jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_121jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_121jrelibjce.jar;C:Program FilesJavajdk1.8.0_121jrelibjfr.jar;C:Program FilesJavajdk1.8.0_121jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_121jrelibjsse.jar;C:Program FilesJavajdk1.8.0_121jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_121jrelibplugin.jar;C:Program FilesJavajdk1.8.0_121jrelibresources.jar;C:Program FilesJavajdk1.8.0_121jrelibrt.jar;D:mysoftwarejavabasetargetclasses" org.example.MapTest
org.example.MapTest$3

Process finished with exit code 0

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

总结

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/458748.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号