java - Java 枚举是否在 Android 运行时分配堆内存?

标签 java android memory enums heap-memory

我正在观看两位 Android 工程师谈论 Android 中的垃圾收集的视频。在介绍中,他们对枚举进行了一些玩笑。 Romain Guy 说:“我必须纠正你。枚举,它们不分配。这就是重点。”起初,我认为罗曼只是开了个玩笑,因为枚举在其他语言中是这样工作的。但在此之后,Chet 似乎承认枚举确实不分配,而是做一些“内存相关”的事情(意味着:生活在堆栈上)。这种 react 让我感到困惑。

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

根据我的理解,Java 中的枚举基本上是类实例的固定集合和 seeing as Enum implements Object从内存角度来看与对象实例化一样好,因此将分配到堆中。

但我可以想象枚举具有一些特殊的地位,因为编译器可以绘制它们的强大属性。类似地,我知道 String 有各种优化,例如文字共享池。

我目前的情况是,我有固定的对象列表,在我的应用程序中用作常量。所以我可以将其实现为枚举或类实例化数组。假设可读性不是问题,那么前者的性能会更高吗?

最佳答案

枚举是对象。像所有对象一样,它们存在于堆中。

确实,如果你反编译一个简单的枚举,例如:

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

您还可以从枚举中获得一些其他特殊的东西(例如保证它们不能反射地创建);但实际上,它们只是普通的对象。

我认为他们试图表达的一点是,枚举不会被分配多次(如果您确实需要单例,它们是实现单例的好方法)。因此,您需要支付少量的固定成本来加载枚举类;但您可以一遍又一遍地重复使用这些相同的实例。

关于java - Java 枚举是否在 Android 运行时分配堆内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53344941/

相关文章:

java - 如何使用 setter 和 getter 方法获取对象的对象数组及其响应

java - 如何使用安装程序在一个简单的 .exe 文件中安装多个安装程序?

android - 无法同时添加 Google Play 服务和 Appcompat-v7 依赖项

memory - 转置数组并实际重新排序内存

java - 使用 jacoco 离线检测的 gradle 每次测试的覆盖率 - java.lang.IllegalStateException : JaCoCo agent not started

java - 如何根据 Key 对 JSON 对象进行排序?

android - Open103R、Open107v开发板——如何编程?

java - vector 仅填充最后一项

java - 为什么 Solaris 上的 Sun Java 占用 RSS 内存的两倍以上?

c# - 64 位 VB.NET 分配 > 2GB 的 RAM(.NET 错误?)