两种分配方式的区别

Difference between two types of allocations

foo[] 示例 = 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 在内部处理这两种分配的方式有区别吗?第一个变体有一个特殊的名字吗?字节码有什么区别?

郑重声明,字节码确实不同。这是为第一个版本生成的字节码:

   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));

第一个版本是all one expression。赋值表达式将值存储到数组中,然后表达式计算为存储的值。所以它都是一个巨大的表达式,相同的值存储在每个数组位置,没有中间读取。

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

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

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

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,第一个版本将立即抛出,而第二个版本将部分填充数组。