两种类型的分配之间的差异

时间:2015-12-30 21:16:39

标签: java performance bytecode

foo [] example = new foo [4];

变体1

example [0] = example [1] = example [2] = example [3] = new foo(5);

变体2

example [0] = new foo(5);
example [1] = example [0];
example [2] = example [0];
example [3] = example [0];

Java如何在内部处理这两个分配有什么不同?让第一个变种有一个特殊名称吗?字节码有什么区别?

2 个答案:

答案 0 :(得分:0)

对于记录,字节码确实不同。这是为第一个版本生成的字节码:

   0: iconst_4      
   1: anewarray     #2                  // class com/foo/Allocation$Foo
   4: astore_1      
   5: aload_1       
   6: iconst_0      
   7: aload_1       
   8: iconst_1      
   9: aload_1       
  10: iconst_2      
  11: aload_1       
  12: iconst_3      
  13: new           #2                  // class com/foo/Allocation$Foo
  16: dup           
  17: iconst_5      
  18: invokespecial #3                  // Method com/foo/Allocation$Foo."<init>":(I)V
  21: dup_x2        
  22: aastore       
  23: dup_x2        
  24: aastore       
  25: dup_x2        
  26: aastore       
  27: aastore       
  28: return        

这是为第二个生成的字节码:

   0: iconst_4      
   1: anewarray     #2                  // class com/foo/Allocation$Foo
   4: astore_1      
   5: aload_1       
   6: iconst_0      
   7: new           #2                  // class com/foo/Allocation$Foo
  10: dup           
  11: iconst_5      
  12: invokespecial #3                  // Method com/foo/Allocation$Foo."<init>":(I)V
  15: aastore       
  16: aload_1       
  17: iconst_1      
  18: aload_1       
  19: iconst_0      
  20: aaload        
  21: aastore       
  22: aload_1       
  23: iconst_2      
  24: aload_1       
  25: iconst_0      
  26: aaload        
  27: aastore       
  28: aload_1       
  29: iconst_3      
  30: aload_1       
  31: iconst_0      
  32: aaload        
  33: aastore       
  34: return        

我个人觉得这两个版本的可读性都低于

Arrays.fill(example, new Foo(5));

答案 1 :(得分:0)

第一个版本是一个表达式。赋值表达式使值存储到数组中,然后表达式求值为存储的值。所以它是一个巨大的表达式,并且相同的值存储在每个数组位置,没有插入读取。

在第二个版本中,它每次都从数组中读取。如果你有多线程代码而另一个线程同时修改数组,那么这可能会返回不同的结果。

对于单线程代码,它们实际上是完全相同的。

注意:这是第一个版本的内容,添加了括号以表示评估顺序。

example [0] = (example [1] = (example [2] = (example [3] = (new foo(5)))));

它等同于以下代码(注意缺少数组读取)

foo t = new foo(5);
example[3] = t;
example[2] = t;
example[1] = t;
example[0] = t;

P.S。另一个区别是它们以相反的顺序分配数组元素。因此,如果数组的长度小于4,则第一个版本将立即抛出,而第二个版本将部分填充数组。