Double {{ }} syntax question in java
Possible Duplicates:
Efficiency of Java “Double Brace Initialization”?
Meaning of new Class(…){{…}} initialization idiom
假设我创建了一个jmenu栏,方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <wyn> JMenuItem saveMenuItem = new JMenuItem("Save") {{ addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String location = GUI.Custom.QuickDialogs.selectFile(false); try { PrintWriter pw = new PrintWriter(new File(location)); String text = textArea.getText(); pw.println(text); pw.flush(); pw.close(); } catch(Exception ex) { textArea.append("Could not save this debug output"); } } }); }}; JMenu optionsMenu = new JMenu("Options") {{ add(saveMenuItem); setVisible(true); }}; private JMenuBar menuBar = new JMenuBar() {{ add(optionsMenu); setVisible(true); }}; </wyn> |
用这种方式创建对象而不只是声明变量,然后在构造函数或其他东西中创建对象,这是一种糟糕的设计模式吗?
您所做的操作称为"初始化块"。
来自DOC:
The Java compiler copies initializer
blocks into every constructor.
Therefore, this approach can be used
to share a block of code between
multiple constructors
例子:
1 2 3 4 5 6 7 8 9 |
但在我看来,我们不应该经常使用它,尤其是在您的情况下,使用它是非常不寻常的。
双括号初始化实际上没有什么问题;我经常将它用于映射和列表。
这可能取决于你的听众是谁——你团队中的其他人明白你在这里做什么吗?记住,总有一天,会有人读到这段代码。
你好像在问(至少)两个不同的问题。双括号习惯用法是已知的,常用作创建匿名内部类的简写,将显式构造函数替换为初始值设定项块。通常这会使代码更具可读性,所以我认为这是可以的。
由于(非静态)初始值设定项块是语言的一个相对较新的添加,因此一些开发人员可能不熟悉它们,这可能会造成混淆。当然,和几乎所有的技术一样,当过度使用时,它会产生比它解决的问题更多的问题。
两个问题
泄漏引用:由于这些是匿名的内部类,所以它们保留对周围对象的引用,从而防止收集它们。这可能导致难以找到内存泄漏。
匿名类型:对于任何依赖于确切类的内容,这都可能导致问题。例如,序列化和Equals的某些实现可能无法按预期工作。
如果您知道上面的内容不会有问题,那么使用这种语法没有任何问题。
像大多数这种性质的问题一样,不幸的是,我必须说"视情况而定"。当你这样做的时候,你实际上是在创建一个新的匿名类,所以在内存和CPU方面有一个非常小的性能冲击,但是在大多数情况下,我会说这是微不足道的,足以忽略。如果这样做可以使代码更具可读性,并且是团队其他成员使用的样式,那么我建议您使用它。