Распределяет ли перечисление Java память кучи в среде выполнения Android? - PullRequest
0 голосов
/ 16 ноября 2018

Я смотрел видео двух инженеров Android, рассказывающих о сборке мусора в Android.Во введении они немного шутят над перечислениями.Ромэн Гай говорит: «Я должен исправить тебя там. Перечисления, они не распределяются. В этом весь смысл».Сначала я, что Ромен только что пошутил, потому что перечисления работают так на других языках.Но после этого Чет, похоже, соглашается с тем, что перечисления действительно не распределяют, а выполняют некоторые «связанные с памятью» вещи (подразумевая: жизнь в стеке).Эта реакция меня смущает.

https://youtu.be/Zc4JP8kNGmQ?t=96

В моем понимании перечисления в Java - это в основном фиксированные коллекции экземпляров классов, и видится как Enum реализует Object так же хорошо, как экземпляры объектов с точки зрения памяти, и поэтому будет выделяться в куче.

Но я могу представить, что перечисления имеют какой-то особый статус из-за сильных свойств, которые компилятор может использовать для них.Аналогично, я знаю, что существуют различные оптимизации для String, такие как общий пул для литералов.

В настоящее время я нахожусь в ситуации, когда у меня есть фиксированный список объектов, которые я использую в качестве констант в своем приложении.Так что я могу реализовать это как перечисление или как массив экземпляров классов.Если предположить, что читаемость не является проблемой, будет ли более эффективным сделать первое?

1 Ответ

0 голосов
/ 17 ноября 2018

Перечисления являются объектами.Как и все объекты, они живут в куче.

Действительно, если вы декомпилируете простое перечисление, например:

enum Foo { A, B }

, это выглядит так (некоторые вещи опущены):

  static {};
    Code:
       0: new           #4                  // class Foo
       3: dup
       4: ldc           #7                  // String A
       6: iconst_0
       7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      10: putstatic     #9                  // Field A:LFoo;
      13: new           #4                  // class Foo
      16: dup
      17: ldc           #10                 // String B
      19: iconst_1
      20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      23: putstatic     #11                 // Field B:LFoo;
      26: iconst_2
      27: anewarray     #4                  // class Foo
      30: dup
      31: iconst_0
      32: getstatic     #9                  // Field A:LFoo;
      35: aastore
      36: dup
      37: iconst_1
      38: getstatic     #11                 // Field B:LFoo;
      41: aastore
      42: putstatic     #1                  // Field $VALUES:[LFoo;
      45: return

, который в основном совпадает с классом, подобным этому:

class Bar {
  static final Bar A = new Bar("A");
  static final Bar B = new Bar("B");

  static final Bar[] $VALUES;

  static {
    Bar[] array = new Bar[2];
    array[0] = A;
    array[1] = B;
    $VALUES = array;
  }

  private Bar(String name) {}
}

, который декомпилируется в:

  static {};
    Code:
       0: new           #2                  // class Bar
       3: dup
       4: ldc           #3                  // String A
       6: invokespecial #4                  // Method "<init>":(Ljava/lang/String;)V
       9: putstatic     #5                  // Field A:LBar;
      12: new           #2                  // class Bar
      15: dup
      16: ldc           #6                  // String B
      18: invokespecial #4                  // Method "<init>":(Ljava/lang/String;)V
      21: putstatic     #7                  // Field B:LBar;
      24: iconst_2
      25: anewarray     #2                  // class Bar
      28: astore_0
      29: aload_0
      30: iconst_0
      31: getstatic     #5                  // Field A:LBar;
      34: aastore
      35: aload_0
      36: iconst_1
      37: getstatic     #7                  // Field B:LBar;
      40: aastore
      41: aload_0
      42: putstatic     #8                  // Field $VALUES:[LBar;
      45: return

Есть несколько других специальных вещей, которые вы получаете из перечисления(например, гарантии, что они не могут быть отражены);но на самом деле они являются обычными объектами.

Я думаю, что они пытаются подчеркнуть, что перечисления не выделяются более одного раза (это хороший способ реализации одиночных символов, если вам действительно нужносинглтон).Таким образом, вы платите небольшую фиксированную плату за загрузку класса enum;но вы можете использовать эти экземпляры снова и снова.

...