- void Method1()
- {
- byte [] bytearray = new byte[16];
- /* some code */
- }
- void Method2()
- {
- byte [] bytearray = {0,0};
- /* some code */
- }
在这两种情况下,假设当Method1和Method2返回时,“bytearray”是垃圾收集的候选者,因为操纵thetearray变量的任何代码都不会在方法本身的结尾处保留引用.
Method2是否通过避免对“新”的呼叫进行更快(或不同的)操作?还是两个以上的实现呢?在这两种情况下,Java编译器或运行时都可以进行优化,以避免针对短暂临时缓冲区的内存分配器造成开销.
解决方法
哪种形式是最好的?几乎总是让你的程序更易读的.
但是有什么实际的区别,不管我们会不会注意到?我们来看一下!
- class ArrayTest {
- public int[] withNew() {
- int[] arr = new int[4];
- return arr;
- }
- public int[] withInitializer() {
- int[] arr = {0,0};
- return arr;
- }
- }
我们用javap -c ArrayTest来反汇编:
- Compiled from "ArrayTest.java"
- class ArrayTest {
- ArrayTest();
- Code:
- 0: aload_0
- 1: invokespecial #1 // Method java/lang/Object."<init>":()V
- 4: return
- public int[] withNew();
- Code:
- 0: iconst_4
- 1: newarray int
- 3: astore_1
- 4: aload_1
- 5: areturn
- public int[] withInitializer();
- Code:
- 0: iconst_4
- 1: newarray int
- 3: dup
- 4: iconst_0
- 5: iconst_0
- 6: iastore
- 7: dup
- 8: iconst_1
- 9: iconst_0
- 10: iastore
- 11: dup
- 12: iconst_2
- 13: iconst_0
- 14: iastore
- 15: dup
- 16: iconst_3
- 17: iconst_0
- 18: iastore
- 19: astore_1
- 20: aload_1
- 21: areturn
- }
不,在这种情况下,它们不一样 – 使用初始化器形式会使插槽被单独设置为0,这是因为它们已经被阵列分配置零了,这是无意义的.所以,这基本上等同于:
- public int[] withNewAndSettingExplicitly() {
- int[] arr = new int[4];
- arr[0] = 0;
- arr[1] = 0;
- arr[2] = 0;
- arr[3] = 0;
- return arr;
- }
虽然编译了另一组字节码,这几乎是相同但不完全相同的:
- public int[] withNewAndSettingExplicitly();
- Code:
- 0: iconst_4
- 1: newarray int
- 3: astore_1
- 4: aload_1
- 5: iconst_0
- 6: iconst_0
- 7: iastore
- 8: aload_1
- 9: iconst_1
- 10: iconst_0
- 11: iastore
- 12: aload_1
- 13: iconst_2
- 14: iconst_0
- 15: iastore
- 16: aload_1
- 17: iconst_3
- 18: iconst_0
- 19: iastore
- 20: aload_1
- 21: areturn
因此,故事的道德是这样的:如果您希望所有元素设置为0,则使用新的int [size](这可能或可能不会更快)生成较少的字节码,但是您也必须输入较少的imho是一个大胜利).如果要在阵列中直接设置数组中的值,请在代码中使用最好的代码,因为生成的代码将几乎与您选择的形式相同.
现在,回答你的实际问题:
Does Method2 operate any faster (or differently) by avoiding the call to “new”?
正如我们所看到的,新的只是隐藏在初始化器语法之后(寻找newarray op代码).顺便说一句,分配在JVM中是非常便宜的(代代垃圾收集器有这个愉快的副作用).
Or are the two implementations above equivalent?
正如我们所看到的 – 不完全相同,但是不太可能有人会注意到差异.
In either case,can the Java compiler or runtime make an optimization to avoid the overhead of hitting the memory allocator for this short-lived temporary buffer?
再次 – 分配是便宜的,所以不用担心.然而,最近的JVM具有这样一个叫做escape analysis的小功能,这可能导致阵列被分配而不是堆分配.