是否更快(或更好)在Java中声明数组内联?

前端之家收集整理的这篇文章主要介绍了是否更快(或更好)在Java中声明数组内联?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
考虑以下两个几乎相等的方法调用.注意在两者上声明和分配字节数组的方式.
  1. void Method1()
  2. {
  3. byte [] bytearray = new byte[16];
  4.  
  5. /* some code */
  6.  
  7. }
  8.  
  9. void Method2()
  10. {
  11. byte [] bytearray = {0,0};
  12.  
  13. /* some code */
  14. }

在这两种情况下,假设当Method1和Method2返回时,“bytearray”是垃圾收集的候选者,因为操纵thetearray变量的任何代码都不会在方法本身的结尾处保留引用.

Method2是否通过避免对“新”的呼叫进行更快(或不同的)操作?还是两个以上的实现呢?在这两种情况下,Java编译器或运行时都可以进行优化,以避免针对短暂临时缓冲区的内存分配器造成开销.

解决方法

哪种形式是最快的?取决于JIT – 它们可能是等效的.如果有的话,很少有程序会注意到有差异.

哪种形式是最好的?几乎总是让你的程序更易读的.

但是有什么实际的区别,不管我们会不会注意到?我们来看一下!

  1. class ArrayTest {
  2.  
  3. public int[] withNew() {
  4. int[] arr = new int[4];
  5. return arr;
  6. }
  7.  
  8. public int[] withInitializer() {
  9. int[] arr = {0,0};
  10. return arr;
  11. }
  12.  
  13. }

我们用javap -c ArrayTest来反汇编:

  1. Compiled from "ArrayTest.java"
  2. class ArrayTest {
  3. ArrayTest();
  4. Code:
  5. 0: aload_0
  6. 1: invokespecial #1 // Method java/lang/Object."<init>":()V
  7. 4: return
  8.  
  9. public int[] withNew();
  10. Code:
  11. 0: iconst_4
  12. 1: newarray int
  13. 3: astore_1
  14. 4: aload_1
  15. 5: areturn
  16.  
  17. public int[] withInitializer();
  18. Code:
  19. 0: iconst_4
  20. 1: newarray int
  21. 3: dup
  22. 4: iconst_0
  23. 5: iconst_0
  24. 6: iastore
  25. 7: dup
  26. 8: iconst_1
  27. 9: iconst_0
  28. 10: iastore
  29. 11: dup
  30. 12: iconst_2
  31. 13: iconst_0
  32. 14: iastore
  33. 15: dup
  34. 16: iconst_3
  35. 17: iconst_0
  36. 18: iastore
  37. 19: astore_1
  38. 20: aload_1
  39. 21: areturn
  40. }

不,在这种情况下,它们不一样 – 使用初始化器形式会使插槽被单独设置为0,这是因为它们已经被阵列分配置零了,这是无意义的.所以,这基本上等同于:

  1. public int[] withNewAndSettingExplicitly() {
  2. int[] arr = new int[4];
  3. arr[0] = 0;
  4. arr[1] = 0;
  5. arr[2] = 0;
  6. arr[3] = 0;
  7. return arr;
  8. }

虽然编译了另一组字节码,这几乎是相同但不完全相同的:

  1. public int[] withNewAndSettingExplicitly();
  2. Code:
  3. 0: iconst_4
  4. 1: newarray int
  5. 3: astore_1
  6. 4: aload_1
  7. 5: iconst_0
  8. 6: iconst_0
  9. 7: iastore
  10. 8: aload_1
  11. 9: iconst_1
  12. 10: iconst_0
  13. 11: iastore
  14. 12: aload_1
  15. 13: iconst_2
  16. 14: iconst_0
  17. 15: iastore
  18. 16: aload_1
  19. 17: iconst_3
  20. 18: iconst_0
  21. 19: iastore
  22. 20: aload_1
  23. 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小功能,这可能导致阵列被分配而不是堆分配.

猜你在找的Java相关文章