枚举不是Enum的子?

时间:2014-09-11 14:58:37

标签: java enums

Enum类的方法getDeclaringClass()首先查找枚举值是否为枚举值,即它的超级是Enum。如果没有,返回给定实例所生成的类的超类:

public final Class<E> getDeclaringClass() {
    Class<?> clazz = getClass();
    Class<?> zuper = clazz.getSuperclass();
    return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
}

getDeclaringClass()方法运行的实例如何不能是instanceof Enum类? 枚举类型不能扩展,因此枚举类的唯一超类是Enum

所以 - 在下面的例子中:

public enum Dirs {
    NORTH, SOUTH, EAST, WEST 
}

DirsEnum的子类。但是,Dirs本身不能有子类 - 它不能扩展 四个方向中任意一个的getDeclaringClass() - NORTH.getDeclaringClass() DirsNORTH.getClass(),即getDeclaringClass()

NORTH的源代码表明,Enum可能存在NORTH.getDeclaringClass()以外的超类NORTH.getClass()。我不明白这是怎么发生的。

我错过了什么?

编辑:

更具体地说:如何Dirs 返回{{1}},{{1}}。

2 个答案:

答案 0 :(得分:4)

并不完全正确,您无法扩展自己的枚举类。例如,在

的情况下
enum Dirs {

    NORTH {
        @Override
        public Dirs getOppositeDirection() {
            return SOUTH;
        }
    }, 
    SOUTH {
        @Override
        public Dirs getOppositeDirection() {
            return NORTH;
        }
    };

    public abstract Dirs getOppositeDirection();
}

Dirs实际上是abstract类,其枚举值NORTHSOUTH是此类的实现,提供了抽象getOppositeDirection方法的主体,意味着他们扩展Dirs

所以如果你打电话

System.out.println(Dirs.NORTH.getDeclaringClass());
System.out.println(Dirs.SOUTH.getDeclaringClass());
System.out.println(Dirs.NORTH.getClass());
System.out.println(Dirs.SOUTH.getClass());

您将看到类似

的输出
class yourPackage.Dirs
class yourPackage.Dirs
class yourPackage.Dirs$1
class yourPackage.Dirs$2

这意味着getClass将返回实现此枚举的实际类,而getDeclaringClass将返回枚举本身。

BTW:Enum不需要是抽象的,让你通过接受enum的扩展来为某些方法提供特定的实现。您也可以执行类似

的操作
enum MyEnum {
    FOO {
        @Override
        public String toString() {
            return "Foo";
        }
    },
    BAR{
        public String toString() {
            return "baR";
        }
    };
}

BAR.getDeclaringClass()将返回MyEnum,而BAR.getClass()的结果将为MyEnum$2

答案 1 :(得分:1)

考虑到你的枚举有行为,那么每个实例都可以拥有它自己的实现。

public enum Dirs {
    NORTH {
      public Point move(Point p) { return p.move(0, 1); }
    }, 

    SOUTH {
      public Point move(Point p) { return p.move(0, -1); }
    }, 

    EAST {
      public Point move(Point p) { return p.move(1, 0); }
    }, 

    WEST {
      public Point move(Point p) { return p.move(-1, 0); }
    }

    public abstract Point move(Point p);
}

class Point{
    private final int x, y;
    public Point(int x, int y) { this.x = x; this.y = y; }
    public Point move(int dx, int dy) { return new Point(x + dx, y + dy); }
}

现在

assert Dirs.NORTH.getClass() != Dirs.SOUTH.getClass();

,而

assert Dirs.NORTH.getDeclaringClass() == Dirs.SOUTH.getDeclaringClass();

希望这有帮助。