在Java中,使用Sun的JDK 1.6,具有如下所示的枚举:
public enum MyEnum {
FIRST_MEMBER { public void foo() { } },
SECOND_MEMBER { public void foo() { } },
THIRD_MEMBER { public void foo() { } };
}已编译的文件如下:
MyEnum$1.class MyEnum$2.class MyEnum$3.class MyEnum.class 这也意味着显示foo()的堆栈跟踪,或者打印在JVisualVM等中的方法调用,在顶部将有类似的内容:
mypackage.MyEnum$1.run()类名中的$1是由正在编译为匿名内部类的枚举成员造成的。我想知道是否可以安全地假定这些类名中使用的数字映射到定义枚举成员的顺序?如果不是,是否有一种标准的、有保证的方法从用作匿名类名的数字中查找enum成员?
编辑
关于enum的设计,这仅用于说明目的。真正的枚举实现了一个接口,每个成员都提供了方法的不同实现。请不要太在意那些看起来有点奇怪的东西。
编辑#2
为了澄清这一点,我并不打算以编程的方式处理这些信息(比如奇怪的反射废话)。相反,我正在查看堆栈跟踪和分析信息,并试图将对enum成员的方法调用(显示为对匿名类的调用)映射到源代码中的实际enum成员。
发布于 2010-10-22 17:20:15
在堆栈跟踪中,您还将在源文件中获得行号。假设你有源,那就会显示它是哪一个常量。(在eclipse中,只需单击控制台视图中的行号即可直接导航到源)。
要找到类的常量名称,您可以获取枚举的类文件,然后反汇编静态初始化程序。例如,如果您编译:
enum PieceColor {
Black {
@Override public String toString() { return "dark";}
},
White {
@Override public String toString() { return "light";}
}
}然后做:
javap -c PieceColor你得到:
static {};
Code:
0: new #13; //class tools/PieceColor$1
3: dup
4: ldc #15; //String Black
6: iconst_0
7: invokespecial #16; //Method tools/PieceColor$1."<init>":(Ljava/lang/String;I)V
10: putstatic #20; //Field Black:Ltools/PieceColor;
13: new #22; //class tools/PieceColor$2
16: dup
17: ldc #24; //String White
19: iconst_1
20: invokespecial #25; //Method tools/PieceColor$2."<init>":(Ljava/lang/String;I)V
23: putstatic #26; //Field White:Ltools/PieceColor;但是,可能有一个更优雅的方法,但如果其他方法都失败了,这应该是可行的。
发布于 2010-10-22 16:28:05
你想用匿名类名做什么?如果你提供更多的细节,我们可能会提供更好的解决方案。
我猜这个类的名字等于ordinal() + 1。但是,这是一个实现细节,在引入或删除枚举成员时可能会发生更改,因此不建议依赖它。
有效的Java第二版,第31项详细解释了为什么使用实例字段而不是序号更好。
发布于 2010-10-22 16:29:27
您可以与MyEnum.FIRST_MEMBER.getClass().getName()进行比较,这将给出为匿名类生成的名称。
匿名类命名的顺序可能是一致的,但没有得到保证,所以我建议不要依赖它。
您还可以使用非匿名类,在这种情况下,您将知道每个类的名称。
如果您被迫使用匿名类,并且不想在代码中这样做,我相信您只需要尝试手动跟踪。
但是,您可以使用我的上述代码作为调试工具,方法是将其作为辅助方法运行或在调试器中运行。这样,您就可以确认哪个匿名类正在接收每个名称。
https://stackoverflow.com/questions/3998861
复制相似问题