Java中的双括号初始化是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1958636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is Double Brace initialization in Java?
提问by sgokhales
What is Double Brace initialization syntax ({{ ... }}
) in Java?
{{ ... }}
Java 中的双括号初始化语法 ( ) 是什么?
采纳答案by Brian Agnew
Double brace initialisation creates an anonymous class derived from the specified class (the outerbraces), and provides an initialiser block within that class (the innerbraces). e.g.
双花括号初始化创建一个从指定类(外花括号)派生的匿名类,并在该类(内花括号)中提供一个初始化块。例如
new ArrayList<Integer>() {{
add(1);
add(2);
}};
Note that an effect of using this double brace initialisation is that you're creating anonymous inner classes. The created class has an implicit this
pointer to the surrounding outer class. Whilst not normally a problem, it can cause grief in some circumstances e.g. when serialising or garbage collecting, and it's worth being aware of this.
请注意,使用此双括号初始化的效果是您正在创建匿名内部类。创建的类有一个this
指向周围外部类的隐式指针。虽然通常不是问题,但在某些情况下(例如在序列化或垃圾收集时)可能会导致悲伤,并且值得注意这一点。
回答by miku
It's - among other uses - a shortcut for initializing collections. Learn more ...
它是 - 除其他用途外 - 初始化集合的快捷方式。了解更多 ...
回答by Chuck Vose
This would appear to be the same as the with keyword so popular in flash and vbscript. It's a method of changing what this
is and nothing more.
这似乎与在 flash 和 vbscript 中如此流行的 with 关键字相同。这是一种改变现状的方法,this
仅此而已。
回答by akuhn
For a fun application of double brace initialization, see here Dwemthy's Array in Java.
有关双括号初始化的有趣应用,请参阅此处的 Java 中的 Dwemthy 数组。
An excerpt
摘录
private static class IndustrialRaverMonkey
extends Creature.Base {{
life = 46;
strength = 35;
charisma = 91;
weapon = 2;
}}
private static class DwarvenAngel
extends Creature.Base {{
life = 540;
strength = 6;
charisma = 144;
weapon = 50;
}}
And now, be prepared for the BattleOfGrottoOfSausageSmells
and … chunky bacon!
现在,准备好吃BattleOfGrottoOfSausageSmells
……厚实的培根!
回答by dhblah
you mean something like this?
你的意思是这样的?
List<String> blah = new ArrayList<String>(){{add("asdfa");add("bbb");}};
it's an array list initialization in creation time (hack)
这是创建时的数组列表初始化(hack)
回答by Anton Dozortsev
You can put some Java statements as loop to initialize collection:
您可以将一些 Java 语句作为循环来初始化集合:
List<Character> characters = new ArrayList<Character>() {
{
for (char c = 'A'; c <= 'E'; c++) add(c);
}
};
Random rnd = new Random();
List<Integer> integers = new ArrayList<Integer>() {
{
while (size() < 10) add(rnd.nextInt(1_000_000));
}
};
But this case affect to performance, check this discussion
但是这种情况会影响性能,请查看此讨论
回答by Lukas Eder
Every time someone uses double brace initialisation, a kitten gets killed.
每次有人使用双括号初始化时,都会有一只小猫被杀死。
Apart from the syntax being rather unusual and not really idiomatic (taste is debatable, of course), you are unnecessarily creating two significant problems in your application, which I've just recently blogged about in more detail here.
除了语法相当不寻常且不是真正惯用的(当然,品味值得商榷)之外,您在应用程序中不必要地创建了两个重大问题,我最近刚刚在博客中更详细地介绍了这些问题。
1. You're creating way too many anonymous classes
1. 你创建了太多匿名类
Each time you use double brace initialisation a new class is made. E.g. this example:
每次使用双括号初始化时,都会创建一个新类。例如这个例子:
Map source = new HashMap(){{
put("firstName", "John");
put("lastName", "Smith");
put("organizations", new HashMap(){{
put("0", new HashMap(){{
put("id", "1234");
}});
put("abc", new HashMap(){{
put("id", "5678");
}});
}});
}};
... will produce these classes:
...将产生这些类:
Test.class
Test.class
Test.class
Test.class
Test.class
That's quite a bit of overhead for your classloader - for nothing! Of course it won't take much initialisation time if you do it once. But if you do this 20'000 times throughout your enterprise application... all that heap memory just for a bit of "syntax sugar"?
这对您的类加载器来说是相当多的开销 - 一无所获!当然,如果你做一次,它不会花费太多初始化时间。但是,如果您在整个企业应用程序中执行此操作 20'000 次...所有堆内存只是为了一点“语法糖”?
2. You're potentially creating a memory leak!
2. 您可能会造成内存泄漏!
If you take the above code and return that map from a method, callers of that method might be unsuspectingly holding on to very heavy resources that cannot be garbage collected. Consider the following example:
如果您采用上述代码并从方法返回该映射,则该方法的调用者可能会毫无防备地持有无法被垃圾收集的非常重的资源。考虑以下示例:
public class ReallyHeavyObject {
// Just to illustrate...
private int[] tonsOfValues;
private Resource[] tonsOfResources;
// This method almost does nothing
public Map quickHarmlessMethod() {
Map source = new HashMap(){{
put("firstName", "John");
put("lastName", "Smith");
put("organizations", new HashMap(){{
put("0", new HashMap(){{
put("id", "1234");
}});
put("abc", new HashMap(){{
put("id", "5678");
}});
}});
}};
return source;
}
}
The returned Map
will now contain a reference to the enclosing instance of ReallyHeavyObject
. You probably don't want to risk that:
返回的Map
现在将包含对 的封闭实例的引用ReallyHeavyObject
。您可能不想冒险:
Image from http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/
图片来自http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/
3. You can pretend that Java has map literals
3. 你可以假装 Java 有地图文字
To answer your actual question, people have been using this syntax to pretend that Java has something like map literals, similar to the existing array literals:
为了回答您的实际问题,人们一直在使用这种语法来假装 Java 具有类似于地图文字的东西,类似于现有的数组文字:
String[] array = { "John", "Doe" };
Map map = new HashMap() {{ put("John", "Doe"); }};
Some people may find this syntactically stimulating.
有些人可能会发现这在句法上很刺激。
回答by Premraj
- The first brace creates a new Anonymous Inner Class.
- The second set of brace creates an instance initializers like static block in Class.
- 第一个大括号创建一个新的匿名内部类。
- 第二组大括号创建了一个实例初始化器,如类中的静态块。
For example:
例如:
public class TestHashMap {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<String,String>(){
{
put("1", "ONE");
}{
put("2", "TWO");
}{
put("3", "THREE");
}
};
Set<String> keySet = map.keySet();
for (String string : keySet) {
System.out.println(string+" ->"+map.get(string));
}
}
}
How it works
这个怎么运作
First bracecreates a new Anonymous Inner Class. These inner classes are capable of accessing the behavior of their parent class. So, in our case, we are actually creating a subclass of HashSet class, so this inner class is capable of using put() method.
第一个大括号创建一个新的匿名内部类。这些内部类能够访问其父类的行为。所以,在我们的例子中,我们实际上是在创建 HashSet 类的子类,所以这个内部类能够使用 put() 方法。
And Second set of bracesare nothing but instance initializers. If you remind core java concepts then you can easily associate instance initializer blocks with static initializers due to similar brace like struct. Only difference is that static initializer is added with static keyword, and is run only once; no matter how many objects you create.
而第二组括号都不过是实例初始化。如果您提醒核心 Java 概念,那么您可以轻松地将实例初始值设定项块与静态初始值设定项相关联,因为类似于结构的大括号。唯一不同的是静态初始化器添加了static关键字,并且只运行一次;无论您创建了多少对象。
回答by Boris Podchezertsev
To avoid all negative effects of double brace initialization, such as:
为了避免双括号初始化的所有负面影响,例如:
- Broken "equals" compatibility.
- No checks performed, when use direct assignments.
- Possible memory leaks.
- 破坏“等于”兼容性。
- 使用直接赋值时不执行检查。
- 可能的内存泄漏。
do next things:
做接下来的事情:
- Make separate "Builder" class especially for double brace initialization.
- Declare fields with default values.
- Put object creation method in that class.
- 制作单独的“Builder”类,特别是用于双括号初始化。
- 使用默认值声明字段。
- 将对象创建方法放在该类中。
Example:
例子:
public class MyClass {
public static class Builder {
public int first = -1 ;
public double second = Double.NaN;
public String third = null ;
public MyClass create() {
return new MyClass(first, second, third);
}
}
protected final int first ;
protected final double second;
protected final String third ;
protected MyClass(
int first ,
double second,
String third
) {
this.first = first ;
this.second= second;
this.third = third ;
}
public int first () { return first ; }
public double second() { return second; }
public String third () { return third ; }
}
Usage:
用法:
MyClass my = new MyClass.Builder(){{ first = 1; third = "3"; }}.create();
Advantages:
好处:
- Simply to use.
- Do not breaks "equals" compatibility.
- You can perform checks in creation method.
- No memory leaks.
- 简单地使用。
- 不要破坏“等于”兼容性。
- 您可以在创建方法中执行检查。
- 没有内存泄漏。
Disadvantages:
缺点:
- None.
- 没有任何。
And, as a result, we have simplest java builder pattern ever.
因此,我们有最简单的 Java 构建器模式。
See all samples at github: java-sf-builder-simple-example
查看 github 上的所有示例:java-sf-builder-simple-example
回答by ctomek
1- There is no such thing as double braces:
I'd like to point out that there is no such thing as double brace initialization. There is only normal traditional one brace initializaition block. Second braces block has nothing to do with initialization. Answers say that those two braces initialize something, but it is not like that.
1- 没有双大括号这样的东西:
我想指出没有双大括号初始化这样的东西。只有普通的传统大括号初始化块。第二个大括号块与初始化无关。答案说这两个大括号初始化了一些东西,但事实并非如此。
2- It's not just about anonymous classes but all classes:
Almost all answers talk that it is a thing used when creating anonymous inner classes. I think that people reading those answers will get the impression that this is only used when creating anonymous inner classes. But it is used in all classes. Reading those answers it looks like is some brand new special feature dedicated to anonymous classes and I think that is misleading.
2- 不仅仅是匿名类,而是所有类:
几乎所有的答案都说它是创建匿名内部类时使用的东西。我认为阅读这些答案的人会觉得这仅在创建匿名内部类时使用。但它用于所有类。阅读这些答案,它看起来像是一些专用于匿名课程的全新特殊功能,我认为这是一种误导。
3- The purpose is just about placing brackets after each other, not new concept:
Going further, this question talks about situation when second opening bracket is just after first opening bracket. When used in normal class usually there is some code between two braces, but it is totally the same thing. So it is a matter of placing brackets. So I think we should not say that this is some new exciting thing, because this is the thing which we all know, but just written with some code between brackets. We should not create new concept called "double brace initialization".
3-目的只是将括号放在一起,而不是新概念:
更进一步,这个问题讨论了第二个左括号紧接在第一个左括号之后的情况。在普通类中使用时,通常在两个大括号之间有一些代码,但它们完全相同。所以这是一个放置括号的问题。所以我认为我们不应该说这是一些令人兴奋的新事物,因为这是我们都知道的事物,只是在括号之间写了一些代码。我们不应该创建称为“双括号初始化”的新概念。
4- Creating nested anonymous classes has nothing to do with two braces:
I don't agree with an argument that you create too many anonymous classes. You're not creating them because an initialization block, but just because you create them. They would be created even if you did not use two braces initialization so those problems would occur even without initialization... Initialization is not the factor which creates initialized objects.
4- 创建嵌套匿名类与两个大括号无关:
我不同意您创建太多匿名类的论点。您不是因为初始化块而创建它们,而是因为您创建了它们。即使您没有使用两个大括号初始化,它们也会被创建,因此即使没有初始化也会发生这些问题......初始化不是创建初始化对象的因素。
Additionally we should not talk about problem created by using this non-existent thing "double brace initialization" or even by normal one bracket initialization, because described problems exist only because of creating anonymous class so it has nothing to do with original question. But all answers with give the readers impression that it is not fault of creating anonymous classes, but this evil (non-existent) thing called "double brace initialization".
另外我们不应该谈论使用这种不存在的东西“双括号初始化”甚至是普通的单括号初始化所产生的问题,因为所描述的问题只是因为创建匿名类而存在,所以它与原始问题无关。但是所有的答案都给读者的印象是,创建匿名类不是错,而是这种称为“双括号初始化”的邪恶(不存在)东西。