猿问

Java“双支撑初始化”的效率?

Java“双支撑初始化”的效率?

在……里面Java的隐藏特征上面的答案提到双支撑初始化,带着非常诱人的语法:

Set<String> flavors = new HashSet<String>() {{
    add("vanilla");
    add("strawberry");
    add("chocolate");
    add("butter pecan");}};

这个成语创建了一个匿名内部类,其中只有一个实例初始化器,“可以在包含范围内使用任何[.]方法”。

主要问题:这是低效就像听起来一样?它的使用应该仅限于一次性初始化吗?(当然还有炫耀!)

第二个问题:新的HashSet必须是实例初始化器中使用的“this”。有人能说明这个机制吗?

第三个问题:这个成语也是吗?晦涩在生产代码中使用?

摘要:非常好的答案谢谢大家。关于问题(3),人们认为语法应该是清晰的(虽然我建议偶尔发表评论,特别是如果您的代码将传递给可能不熟悉它的开发人员)。

关于问题(1),生成的代码应该运行得很快。额外的.class文件确实会导致JAR文件混乱,程序启动速度会稍微慢一些(这要感谢@coob税务局来测量)。@Thilo指出垃圾收集可能受到影响,在某些情况下,额外加载类的内存开销可能是一个因素。

问题(2)对我来说是最有趣的。如果我理解答案,那么DBI中发生的事情就是匿名内部类扩展了由新操作符构造的对象的类,因此有一个引用正在构造的实例的“this”值。非常整洁。

总的来说,DBI给我的印象是一种智力上的好奇。Coobbird和其他人指出,您可以使用Arrays.asList、varargs方法、Google集合和建议的Java 7集合文本实现同样的效果。Scala、JRuby和Groovy等较新的JVM语言也为列表构造提供了简洁的符号,并与Java进行了良好的互操作。考虑到DBI扰乱了类路径,减缓了类的加载速度,并使代码变得更加模糊,我可能会回避它。不过,我打算把这件事发到一个朋友身上,他刚刚拿到了他的SCJP,并且喜欢有关Java语义的善意的争论!;-)谢谢大家!

7/2017:Baeldung有一个很好的总结双大括号初始化,并认为它是一个反模式。

12/2017:@Basil Bourque指出,在新的Java 9中,您可以说:

Set<String> flavors = Set.of("vanilla", "strawberry", "chocolate", "butter pecan");

这是肯定的路要走。如果您被更早的版本所困扰,请看一看Google集合的ImmutableSet.


梦里花落0921
浏览 398回答 3
3回答

慕沐林林

当我太沉迷于匿名内部类时,问题是:2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1,602&nbsp;DemoApp2$1.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1,976&nbsp;DemoApp2$10.class2009/05/27&nbsp;&nbsp;16:35 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1,919&nbsp;DemoApp2$11.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2,404&nbsp;DemoApp2$12.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1,197&nbsp;DemoApp2$13.class/*&nbsp;snip&nbsp;*/2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1,953&nbsp;DemoApp2$30.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1,910&nbsp;DemoApp2$31.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2,007&nbsp;DemoApp2$32.class2009/05/27&nbsp;&nbsp;16:35&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;926&nbsp;DemoApp2$33$1$1.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4,104&nbsp;DemoApp2$33$1.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2,849&nbsp;DemoApp2$33.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;926&nbsp;DemoApp2$34$1$1.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4,234&nbsp;DemoApp2$34$1.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2,849&nbsp;DemoApp2$34.class/*&nbsp;snip&nbsp;*/2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;614&nbsp;DemoApp2$40.class2009/05/27&nbsp;&nbsp;16:35&nbsp; 2,344&nbsp;DemoApp2$5.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;1,551&nbsp;DemoApp2$6.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;1,604&nbsp;DemoApp2$7.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;1,809&nbsp;DemoApp2$8.class2009/05/27&nbsp;&nbsp;16:35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;2,022&nbsp;DemoApp2$9.class这些类都是在我创建一个简单的应用程序时生成的,并且使用了大量的匿名内部类-每个类都将被编译成一个单独的类。class档案。如前所述,“双大括号初始化”是一个带有实例初始化块的匿名内部类,这意味着为每个“初始化”创建了一个新类,所有这些都是为了创建一个单独的对象。考虑到Java虚拟机在使用这些类时需要读取所有这些类,这可能导致在字节码验证流程之类的。更不用说存储所有这些磁盘所需的磁盘空间的增加了。class档案。在使用双大括号初始化时,似乎存在一定的开销,因此太过使用它可能不是一个好主意。但正如埃迪在评论中所指出的那样,不可能完全肯定其影响。仅供参考,双大括号初始化如下:List<String>&nbsp;list&nbsp;=&nbsp;new&nbsp;ArrayList<String>()&nbsp;{{ &nbsp;&nbsp;&nbsp;&nbsp;add("Hello"); &nbsp;&nbsp;&nbsp;&nbsp;add("World!");}};它看起来像是Java的“隐藏”特性,但它只是对以下内容的重写:List<String>&nbsp;list&nbsp;=&nbsp;new&nbsp;ArrayList<String>()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Instance&nbsp;initialization&nbsp;block &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add("Hello"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add("World!"); &nbsp;&nbsp;&nbsp;&nbsp;}};所以基本上是实例初始化块这是匿名内部类.约书亚·布洛赫收集文字提案为钱币工程大致如下:List<Integer>&nbsp;intList&nbsp;=&nbsp;[1,&nbsp;2,&nbsp;3,&nbsp;4];Set<String>&nbsp;strSet&nbsp;=&nbsp;{"Apple",&nbsp;"Banana",&nbsp;"Cactus"};Map<String,&nbsp;Integer>&nbsp;truthMap&nbsp;=&nbsp;{&nbsp;"answer"&nbsp;:&nbsp;42&nbsp;};可悲的是不顺既不是Java 7,也不是Java 8,被无限期搁置。实验这是我测试过的一个简单的实验-制造1000ArrayListS与元素"Hello"和"World!"通过add方法,使用以下两种方法:方法1:双支座初始化List<String>&nbsp;l&nbsp;=&nbsp;new&nbsp;ArrayList<String>()&nbsp;{{ &nbsp;&nbsp;add("Hello"); &nbsp;&nbsp;add("World!");}};方法2:实例化ArrayList和addList<String>&nbsp;l&nbsp;=&nbsp;new&nbsp;ArrayList<String>();l.add("Hello");l.add("World!");我创建了一个简单的程序来编写Java源文件,使用以下两种方法执行1000个初始化:试验1:class&nbsp;Test1&nbsp;{ &nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;s)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;long&nbsp;st&nbsp;=&nbsp;System.currentTimeMillis(); &nbsp;&nbsp;&nbsp;&nbsp;List<String>&nbsp;l0&nbsp;=&nbsp;new&nbsp;ArrayList<String>()&nbsp;{{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add("Hello"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add("World!"); &nbsp;&nbsp;&nbsp;&nbsp;}}; &nbsp;&nbsp;&nbsp;&nbsp;List<String>&nbsp;l1&nbsp;=&nbsp;new&nbsp;ArrayList<String>()&nbsp;{{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add("Hello"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add("World!"); &nbsp;&nbsp;&nbsp;&nbsp;}}; &nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;snip&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;List<String>&nbsp;l999&nbsp;=&nbsp;new&nbsp;ArrayList<String>()&nbsp;{{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add("Hello"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add("World!"); &nbsp;&nbsp;&nbsp;&nbsp;}}; &nbsp;&nbsp;&nbsp;&nbsp;System.out.println(System.currentTimeMillis()&nbsp;-&nbsp;st); &nbsp;&nbsp;}}试验2:class&nbsp;Test2&nbsp;{ &nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;s)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;long&nbsp;st&nbsp;=&nbsp;System.currentTimeMillis(); &nbsp;&nbsp;&nbsp;&nbsp;List<String>&nbsp;l0&nbsp;=&nbsp;new&nbsp;ArrayList<String>(); &nbsp;&nbsp;&nbsp;&nbsp;l0.add("Hello"); &nbsp;&nbsp;&nbsp;&nbsp;l0.add("World!"); &nbsp;&nbsp;&nbsp;&nbsp;List<String>&nbsp;l1&nbsp;=&nbsp;new&nbsp;ArrayList<String>(); &nbsp;&nbsp;&nbsp;&nbsp;l1.add("Hello"); &nbsp;&nbsp;&nbsp;&nbsp;l1.add("World!"); &nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;snip&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;List<String>&nbsp;l999&nbsp;=&nbsp;new&nbsp;ArrayList<String>(); &nbsp;&nbsp;&nbsp;&nbsp;l999.add("Hello"); &nbsp;&nbsp;&nbsp;&nbsp;l999.add("World!"); &nbsp;&nbsp;&nbsp;&nbsp;System.out.println(System.currentTimeMillis()&nbsp;-&nbsp;st); &nbsp;&nbsp;}}请注意,初始化1000所用的时间ArrayListS和扩展的1000个匿名内部类ArrayList将使用System.currentTimeMillis所以计时器没有很高的分辨率。在我的Windows系统上,分辨率大约是15-16毫秒。两次测试的10次测试结果如下:Test1&nbsp;Times&nbsp;(ms)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Test2&nbsp;Times&nbsp;(ms)----------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;---------------- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;187&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;203&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;203&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;188&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;188&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;187&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;203&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;188&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;188&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;203&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0可以看出,双大括号初始化的执行时间为190 ms左右。同时,ArrayList初始化执行时间为0 ms。当然,计时器决议应该考虑在内,但很可能在15毫秒以下。因此,这两种方法的执行时间似乎有明显的不同。这两种初始化方法确实存在一定的开销。是的,有1000个.class通过编译Test1双支撑初始化测试程序。

Helenr

到目前为止还没有指出这种方法的一个属性是,因为您创建了内部类,所以整个包含类在其作用域中被捕获。这意味着,只要您的集合是活动的,它将保留一个指向包含实例的指针(this$0)和防止垃圾收集,这可能是一个问题。这一点,以及一个新类首先被创建,即使一个普通的HashSet工作得很好(甚至更好),这使得我不想使用这个构造(尽管我真的很想要语法糖)。第二个问题:新的HashSet必须是实例初始化器中使用的“this”。有人能说明这个机制吗?我天真地期望“this”指的是初始化“口味”的对象。这正是内部类的工作方式。他们有自己的this,但是它们也有指向父实例的指针,因此您也可以调用包含对象的方法。在命名冲突的情况下,内部类(在您的示例中是HashSet)优先,但是可以在“this”前面加上一个类名,以获得外部方法。public&nbsp;class&nbsp;Test&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;add(Object&nbsp;o)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Set<String>&nbsp;makeSet()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;HashSet<String>()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add("hello");&nbsp;//&nbsp;HashSet &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Test.this.add("hello");&nbsp;//&nbsp;outer&nbsp;instance&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;}}为了弄清楚正在创建的匿名子类,您也可以在其中定义方法。例如,覆盖HashSet.add()&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Set<String>&nbsp;makeSet()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;HashSet<String>()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add("hello");&nbsp;//&nbsp;not&nbsp;HashSet&nbsp;anymore&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boolean&nbsp;add(String&nbsp;s){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;}
随时随地看视频慕课网APP

相关分类

Java
我要回答