请看 Java Enum definition 和 Why in java enum is declared as Enum<E extends Enum<E>> 一般性的讨论。如果Enum类被定义为
,我想知道究竟会破坏什么(不再是类型安全,或者需要额外的强制转换等)public class Enum<E extends Enum>
我正在使用此代码来测试我的想法:
interface MyComparable<T> {
int myCompare(T o);
}
class MyEnum<E extends MyEnum> implements MyComparable<E> {
public int myCompare(E o) { return -1; }
}
class FirstEnum extends MyEnum<FirstEnum> {}
class SecondEnum extends MyEnum<SecondEnum> {}
有了它,我无法在这种情况下找到任何好处。
PS。我不被允许这样做的事实
class ThirdEnum extends MyEnum<SecondEnum> {}
当MyEnum定义为递归时为 a)不相关,因为有了真正的枚举,你不能仅仅因为你不能自己延长枚举而这样做 b)不正确 - 请在编译器中尝试它并看到它实际上能够编译没有任何错误
PPS。我越来越倾向于认为这里的正确答案是“如果删除递归部分,没有什么会改变” - 但我简直无法相信。
答案 0 :(得分:2)
嗯,首先它会抱怨使用原始类型,但你可以这样做:
public class Enum<E extends Enum<?>>
同样的效果。
此外,通过这种类型的通用,您可以执行以下操作:
class FirstEnum extends MyEnum<SecondEnum> {
}
class SecondEnum extends MyEnum<FirstEnum> {
}
对我来说似乎可能会导致很多麻烦。更准确地说,你不能将FirstEnum类型的枚举与同一类型的枚举进行比较,你必须将它与另一种类型的枚举进行比较,如果你想要一个List<FirstEnum>
排序,这真的很麻烦。如果我将E
设置为o ?
,则该示例将无法编译,因为SecondEnum不属于E extends MyEnum<E>
类型(这将导致循环继承)。它会在FirstEnum extends MyEnum<FirstEnum>
时起作用(这意味着SecondEnum是FirstEnum的子类 - 正常的层次继承)。
答案 1 :(得分:1)
考虑Enum<E>.compareTo(E other)
。
这:
ordinal()
上声明的Enum
方法获取枚举的序数值。如果没有当前的限制,你会如何提出这项工作?
这只是我提出的第一个......我相信还有很多其他人。基本上它是一种说法,“你不应该试图将所有枚举视为彼此等同 ... ...枚举本身就是一个封闭的集合,但所有枚举共享某些属性。”< / p>
答案 2 :(得分:1)
我认为这样做的一个令人信服的理由是它使MyEnum类中的代码更加类型安全。
考虑到递归部分可以做到这一点:
class MyEnum<E extends MyEnum<E>> {
private Thing<E> util1() { return someObject }
private void util2(E e) {}
public int method(E o) {
Thing<E> thingy = o.util1();
// You can call the util1 method on o and get a type safe return element.
E o1 = // I don't care how you get a parametrized E object.
o.util2(o1);
// You can call the util2 method with a typesafe parameter.
}
}
简而言之,该递归允许您将类型安全方法放在可以在任何E元素上调用的Enum类中,并且这些调用将是类型安全的。
答案 3 :(得分:0)
如果您没有泛型类型参数,那么您将无法为您创建的枚举的特定子类型扩展Comparable<T extends Comparable>
。
您可以忽略这一点,并创建自己的MyEnum类型,其行为大致相同,但不受不同MyEnum无法比较的限制:
public abstract class MyEnum implements Comparable<MyEnum>
{
private final int ordinal;
protected MyEnum ( int ordinal )
{
this.ordinal = ordinal;
}
public int ordinal ()
{
return ordinal ;
}
public int compareTo ( MyEnum other )
{
return ordinal - other.ordinal; // ignore overflow for now
}
public boolean equals (Object other) {
return ordinal == ((MyEnum)other).ordinal;
}
public int hashCode () {
return ordinal;
}
}
这与枚举对定义的操作的行为大致相同,但不是通用类型安全实现服从LSP - MyEnum的不同子类的对象如果相同或相等具有相同的序数值。
public static class EnumA extends MyEnum
{
private EnumA ( int ordinal ) { super ( ordinal ); }
public static final EnumA a = new EnumA ( 0 );
public static final EnumA b = new EnumA ( 1 );
}
public static class EnumB extends MyEnum
{
private EnumB ( int ordinal ) { super ( ordinal ); }
public static final EnumB x = new EnumB ( 0 );
public static final EnumB y = new EnumB ( 1 );
}
public static void main ( String...args )
{
System.out.println ( EnumA.a.compareTo ( EnumB.x ) );
System.out.println ( EnumA.a.equals ( EnumB.x ) );
System.out.println ( EnumA.a.compareTo ( EnumB.y ) );
System.out.println ( EnumA.a.equals ( EnumB.y ) );
}
在这种情况下,如果您不覆盖equals
,则会失去x.comparesTo(y)=0
暗示x.equals(y)
的约定;如果你覆盖equals,那么有些情况x.equals(y)
并不暗示x == y
(和其他值对象一样),而对于Java枚举,两个相等的测试都会产生相同的结果。
答案 4 :(得分:0)
`X extends Enum<Y>`
是非法的。那个是相关者。编译器可以有enum
的特殊规则,但如果可能的话,为什么没有完美的类型声明?