Is it faster (or better) to declare an array inline in Java?

前端 未结 7 1189
慢半拍i
慢半拍i 2021-01-11 17:20

Consider the following two method calls that are nearly equivalent. Take note of the way the byte array is declared and allocated on both.

void Method1()
{
          


        
相关标签:
7条回答
  • 2021-01-11 17:44

    These 2 methods are exactly equivalent. However second method is more verbose and less convenient for longer arrays or if you want to modify the array length.

    0 讨论(0)
  • 2021-01-11 17:46

    Which form is the fastest? Depends on the JIT - it's possible they're equivalent. Very few, if any, programs will ever notice the difference if there is any.

    Which form is the best? Almost invariably, the one that leaves your program more readable.

    But is there any actual difference, regardless of if we'll ever notice? Let's have a look!

    class ArrayTest {
    
        public int[] withNew() {
            int[] arr = new int[4];
            return arr;
        }
    
        public int[] withInitializer() {
            int[] arr = {0, 0, 0, 0};
            return arr;
        }
    
    }
    

    We disassemble this with 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       
    }
    

    Nope, they're not the same in this case - using the initializer form causes the slots to be individually set to 0, which is kind of pointless since they're already zeroed by the array allocation. So, it's basically equivalent to this:

    public int[] withNewAndSettingExplicitly() {
        int[] arr = new int[4];
        arr[0] = 0;
        arr[1] = 0;
        arr[2] = 0;
        arr[3] = 0;
        return arr;
    }
    

    although that compiles to yet another set of byte code, which is mostly the same but not quite:

      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 
    

    Thus, the moral of the story is this: If you want all elements set to 0, you're generating less bytecode with new int[size] (which may or may not be faster), but you also have to type less (which imho is a big win). If you want to set the values in the array directly when you're allocating it, use whatever looks best in your code, because the generated code will be pretty much the same whatever form you choose.

    Now, to answer your actual questions:

    Does Method2 operate any faster (or differently) by avoiding the call to "new"?

    As we saw, the new is just hidden behind the initializer syntax (look for the newarray op code). By the way, allocation is extremely cheap in the JVM (generational garbage collectors have that pleasant side effect).

    Or are the two implementations above equivalent?

    As we saw - not quite, but it's unlikely anyone will ever notice the difference.

    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?

    Again - allocation is cheap, so don't worry. Nevertheless, recent JVMs have this little feature called escape analysis which may result in the array being stack allocated rather than heap allocated.

    0 讨论(0)
  • 2021-01-11 17:54

    They are the same.

    new keyword creates an object. But in Java, arrays are.. objects. See Chapter 10. Arrays:

    In the Java programming language, arrays are objects (§4.3.1), are dynamically created, and may be assigned to variables of type Object (§4.3.2). All methods of class Object may be invoked on an array.
    ..
    An array is created by an array creation expression (§15.10) or an array initializer (§10.6).

    0 讨论(0)
  • 2021-01-11 17:56

    Both are same...as both will occupy the same space over heap...and bytecode would be the option to study it well

    0 讨论(0)
  • 2021-01-11 18:03

    There is no difference between both the ways. It's just 'Syntactic sugar' in syntax.

    0 讨论(0)
  • 2021-01-11 18:03

    Its better to use the first style.

    On the Second style i try to find a non-0. Its guarantees more error-free, and therefore better readable.

    This shorthand has a good reason to be exists!

    0 讨论(0)
提交回复
热议问题