快速业务通道

也说Java的双括符初始化:其实就是令人费解的不规范代码 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-21

也说Java的双括符初始化:其实就是令人费解的不规范代码

时间:2011-01-15 隔叶黄莺

初看 cgaolei 翻译的 Java技巧之双括弧初始化 一文,走马观花,只知用法,未细看后面的解释。蔚为惊艳,心里想 Java 竟然有这么神奇的语法而一直未得知。因为在初始化集合时确实方便不少。原来做某些测试要初始化集合时会用到 commons-lang 包和 JDK 的 Arrays 工具类,现在知道可以这么用了:

01.Map map = new HashMap() {{ 02.        put("Name", "Unmi"); 03.        put("QQ", "1125535"); 04.}}; 05. 06.List stooges = new ArrayList() {{ 07.        add("Larry"); 08.        add("Moe"); 09.        add("Curly"); 10.}};

看起来都是在一条语句里完成,而不需要分步骤写成:

1.Map map = new HashMap(); 2.map.put("Name","Unmi"); 3.map.put("QQ","1125535");

一不小心没好好理解的人可能以为它是什么特别的语法,关键是大括号连一块了,原作者也是在故作姿态,美其名曰:双括弧语法(double-brace syntax)。真是乱花渐欲迷人眼,其实就是匿名类加初始块。该文有解释:第一层括弧 实际是定义了一个内部匿名类 (Anonymous Inner Class),第二层括弧 实际上是一个实例初始化块 (instance initializer block),这个块在内部匿名类构造时被执行。

那怎么去更好理解它呢?如果我们写成如下的方式应该会更好理解吧,提个技巧,在 Eclipse 中对第一段代码按下 Ctrl + Shift + F 就如下了:

1.Map map = new HashMap() { 2.    { 3.        put("Name", "Unmi"); 4.        put("QQ", "1125535"); 5.    } 6.};

其实就是匿名类啊,会创建出一个 HashMap 的子类来,匿名类中一个 {} 括起来的初始化块,里面自然可放置初始化代码。{} 块中的代码编译后会放到 <init>(),也就是构造方法中去,所以可用来初始化实例。如果是写在 TestDoubleBrace 类中,编译后你会看到会生成 TestDoubleBrace$1.class 文件,反编译该文件内容是:

01.final class com.unmi.TestDoubleBrace$1 extends java.util.HashMap{ //创建了一个 HashMap 的子类 TestDoubleBracke$1 02.com.unmi.TestDoubleBrace$1(); 03.  Code: 04.   0:   aload_0 05.   1:   invokespecial   #8; //Method java/util/HashMap."<init>":()V   //{} 中的代码放到了构造方法中去了 06.   4:   aload_0 07.   5:   ldc     #10; //String Name 08.   7:   ldc     #12; //String Unmi 09.   9:   invokevirtual   #14; //Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 10.   12:  pop 11.   13:  aload_0 12.   14:  ldc     #18; //String QQ 13.   16:  ldc     #20; //String 1125535 14.   18:  invokevirtual   #14; //Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 15.   21:  pop 16.   22:  return 17. 18.}

所以说白了,什么双括弧语法啊,就是代码写得不规范,才使得那么的令人费解。如果还不能理解,再列两个惯用代码来:

01.JFrame frame = new JFrame(); 02.frame.addMouseListener(new MouseAdapter() { 03.    public void mouseClicked(MouseEvent e) { 04.        // do womething here. 05.    } 06.}); 07. 08.Thread thread = new Thread() {{ // 也学着样把大括号也连一块写了 09.        this.setName("作业处理线程"); 10.    }// 如果不重新定义 run() 方法,那么后面那个大括号也能与这个并一块 11. 12.    public void run() { 13.        // do something here. 14.    } 15.}; 16.thread.start();

应该没问题了吧,上面是事件监听器和多线程常用的写法,如果他不把大括号连在一起,而是规范的写代码,相信您一开始也不会对所谓的 Double Brace Syntax 有太多的困惑。要说这种初始化方法运用到集合中还挺方便的,只是无端的多了些匿名类。

刚开始我看到这种双括符写法也是把它奉若圣经,对它只一知半解,昨天在用 XStream 把一个对象生成 XML 文件时,其中有一个 List 属性,我就借用了这种双括符法来初始化元素,结果生成的 XML 文件走了样,原因是 XStream 的 Converter 能处理 ArrayList,但无法很好的处理生成的 ArrayList 的匿名子类。因此才回头认真的重新审视了一番这个所谓的双括符初始化语法。

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号