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的小功能,这可能导致阵列被分配而不是堆分配.