效率:通用数组与对象数组

mat*_*oni 1 java generics performance

假设,您必须经常调用T get(int)从底层数组返回对象的操作.基本上,这可以通过两种方式实现:

class GenericArray<T> {
    final T[] underlying;
    GenericArray(Class<T> clazz, int length) {
        underlying = (T[]) Array.newInstance(clazz, length);
    }
    T get(int i) { return underlying[i]; }
}
Run Code Online (Sandbox Code Playgroud)

class ObjectArray<T> {
    final Object[] underlying;
    ObjectArray(int length) {
        underlying = new Object[length];
    }
    T get(int i) { return (T) underlying[i]; }
}
Run Code Online (Sandbox Code Playgroud)

第一个是使用反射,因此在创建时会更慢.第二个是使用向下转换,这引入了一些开销.由于运行时的泛型类型擦除,必须有一些隐式的转换机制.

所以,这两者在谈到时是否相同get(i)

lex*_*ore 8

我们来看看字节码:

Compiled from "ObjectArray.java"
class lines.ObjectArray<T> {
  final java.lang.Object[] underlying;

  lines.ObjectArray(int);
    Code:
       0: aload_0
       1: invokespecial #10                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: iload_1
       6: anewarray     #3                  // class java/lang/Object
       9: putfield      #13                 // Field underlying:[Ljava/lang/Object;
      12: return

  T get(int);
    Code:
       0: aload_0
       1: getfield      #13                 // Field underlying:[Ljava/lang/Object;
       4: iload_1
       5: aaload
       6: areturn
}


Compiled from "GenericArray.java"
class lines.GenericArray<T> {
  final T[] underlying;

  lines.GenericArray(java.lang.Class<T>, int);
    Code:
       0: aload_0
       1: invokespecial #13                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: aload_1
       6: iload_2
       7: invokestatic  #16                 // Method java/lang/reflect/Array.newInstance:(Ljava/lang/Class;I)Ljava/lang/Object;
      10: checkcast     #22                 // class "[Ljava/lang/Object;"
      13: putfield      #23                 // Field underlying:[Ljava/lang/Object;
      16: return

  T get(int);
    Code:
       0: aload_0
       1: getfield      #23                 // Field underlying:[Ljava/lang/Object;
       4: iload_1
       5: aaload
       6: areturn
}
Run Code Online (Sandbox Code Playgroud)

如您所见,字节码get是相同的.