再谈Java双括弧技巧:不规范的语法?

开发 后端
本文就Java双括弧技巧进行了另一番评论。Java双括弧令初始化集合方便不少,不过似乎其实就是匿名类加初始块。

Java双括弧技巧回顾

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

  1. Map map = new HashMap() {{  
  2.   put("Name""Unmi");  
  3.   put("QQ""1125535");  
  4. }};  
  5.  
  6. List stooges = new ArrayList() {{  
  7.   add("Larry");  
  8.   add("Moe");  
  9.   add("Curly");  
  10. }};  
  11.  

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

  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 文件,反编译该文件内容是:

  1. final class com.unmi.TestDoubleBrace$1 extends java.util.HashMap{ //创建了一个 HashMap 的子类 TestDoubleBracke$1  
  2. com.unmi.TestDoubleBrace$1();  
  3.   Code:  
  4.    0:   aload_0  
  5.    1:   invokespecial   #8//Method java/util/HashMap."<init>":()V   //{} 中的代码放到了构造方法中去了  
  6.    4:   aload_0  
  7.    5:   ldc     #10//String Name  
  8.    7:   ldc     #12//String Unmi  
  9.    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. }  

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

  1. JFrame frame = new JFrame();  
  2. frame.addMouseListener(new MouseAdapter() {  
  3.  public void mouseClicked(MouseEvent e) {  
  4.   // do womething here.  
  5.  }  
  6. });  
  7.  
  8. Thread thread = new Thread() {{ // 也学着样把大括号也连一块写了  
  9.   this.setName("作业处理线程");  
  10.  }// 如果不重新定义 run() 方法,那么后面那个大括号也能与这个并一块  
  11.  
  12.  public void run() {  
  13.   // do something here.  
  14.  }  
  15. };  
  16. thread.start();  
  17.  

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

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

以上就是对Java双括弧技巧的一些思考。本文来自隔叶黄莺 The Blog of Unmi博客,原文名:《也说 Java 的双括符初始化, 其实就是令人费解的不规范代码》

【编辑推荐】

  1. Java语法技巧之双括弧初始化
  2. Java程序调试技巧浅析
  3. 关于Java反射机制的一个实例
  4. 在Java应用程序中使用Jfreechart配置
  5. 浅谈为什么Java接口中不允许定义变量
责任编辑:yangsai 来源: BlogJava
相关推荐

2009-08-12 17:43:54

双括弧Java语法技巧

2012-09-18 09:17:34

Java规范代码代码

2022-05-20 08:17:43

Java日志

2014-03-17 09:34:01

HTMLHTML闭合

2019-10-28 14:37:10

MySQL 数据库收藏

2021-07-31 23:09:42

GPU内存带宽

2009-10-27 14:32:45

VB.NET类型级命名

2024-04-03 09:55:21

代码Go开发

2009-12-29 20:49:47

综合布线不规范现象

2023-01-04 09:29:03

线程业务代码

2013-04-18 17:07:36

2010-06-17 16:27:26

WAP协议

2010-09-28 15:30:39

3550配置dhcp

2023-02-08 09:16:19

Git操作工厂类

2012-05-17 10:02:02

2009-12-09 10:46:06

PHP检查语法错误

2010-06-18 23:01:16

IT管理安防产业H3C

2010-06-21 21:35:28

运维管理安防行业H3C

2009-12-03 15:24:39

双wan路由器设置

2022-09-14 08:22:50

AlloyDB高性能高可用性
点赞
收藏

51CTO技术栈公众号