发现在这个坑是因为代码里用到了cloning库。
在做深度代码拷贝时,发现Enum对象也被Copy了,破坏了Enum对象的唯一性。读了cloning的源代码,其实它考虑了Enum的问题,默认也是跳过的。在其1.9.0版本,它使用了Class.isEnum()来检查,但在1.9.2版本中,检查的代码换成了instanceof Enum, 问题也解决了。对比一下,两种API的区别,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class EnumTest { enum A { A1, A2 { @Override public String toString() { return "this is A2"; } } } public static void main(String[] args) { System.out.println(A.A1.getClass().isEnum()); System.out.println(A.A2.getClass().isEnum()); System.out.println(A.A1 instanceof Enum); System.out.println(A.A2 instanceof Enum); System.out.println(A.A1.getClass()); System.out.println(A.A2.getClass()); } } |
输出是
1 2 3 4 5 6 |
true false true true class sample.EnumTest$A class sample.EnumTest$A$1 |
第二行的输出居然是false, 再看看A2的类签名,不是A,而是一个匿名类A$1。这都是因为A2有Override toString方法,Java产生的了一个匿名类。再看看isEnum的实现,
1 2 3 4 5 6 7 |
public boolean isEnum() { // An enum must both directly extend java.lang.Enum and have // the ENUM bit set; classes for specialized enum constants // don't do the former. return (this.getModifiers() & ENUM) != 0 && this.getSuperclass() == java.lang.Enum.class; } |
这下都清楚了,JDK里使用通过基本类是否是Enum的方法,判断当前类是否是Enum, 但当有匿名类的出现,父类就不再是Enum,isEnum的检查也就失效了。
难道Enum的匿名类就不是Enum了吗?😈
这个坑大家要小心啊!