我正在观看两位Android工程师的视频,他们谈论Android中的垃圾回收。在引言中,他们对枚举有一点玩笑。罗曼·盖伊(Romain Guy)说:“我必须在那儿纠正你。枚举,他们没有分配。这就是重点。”起初,我以为Romain只是在开玩笑,因为枚举在其他语言中是这样工作的。但是在此之后,切特似乎承认确实没有枚举该枚举,而是做了一些与内存相关的事情(暗示:生活在栈上)。这种反应使我感到困惑。
https://youtu.be/Zc4JP8kNGmQ?t=96
据我所知,从内存的角度来看,Java中的枚举基本上是类实例和seeing as Enum
implements Object
的固定集合以及对象实例化,因此将被分配给堆。
但是我可以想象,由于编译器可以利用枚举的强大属性,枚举具有某些特殊的状态。类似地,我知道String
有多种优化方式,例如文字共享池。
我目前处于固定对象列表中,这些对象在应用程序中用作常量。因此,我可以将其实现为枚举或类实例化数组。假设可读性不是问题,那么做前者会不会表现得更好?
答案 0 :(得分:3)
枚举是对象。像所有对象一样,它们生活在堆中。
的确,如果您反编译一个简单的枚举,例如:
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
从枚举中可以得到一些其他特殊的东西(例如保证它们不能被反射地产生);但实际上,它们只是常规对象。
我认为他们要提出的观点是,枚举不会被多次分配(如果您确实需要单例,则这是实现singetons的好方法)。因此,您需要支付少量的固定费用来加载枚举类。但是您可以反复使用这些相同的实例。