加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-14 05:26:50 所属栏目:Java 来源:网络整理
导读:考虑以下两个几乎相等的方法调用.注意在两者上声明和分配字节数组的方式. void Method1(){ byte [] bytearray = new byte[16]; /* some code */}void Method2(){ byte [] bytearray = {0,0}; /* some code */ } 在这两种情况下,假设当Method1和Method2返回时
考虑以下两个几乎相等的方法调用.注意在两者上声明和分配字节数组的方式.
void Method1()
{
    byte [] bytearray = new byte[16];

    /* some code */

}

void Method2()
{
    byte [] bytearray = {0,0};

    /* some code */    
}

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

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

解决方法

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

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

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读