为什么 Java 中的 Enum 上的compareTo是final的?

发布于 2024-07-13 10:25:43 字数 174 浏览 16 评论 0原文

Java 中的枚举实现了 Comparable 接口。 重写Comparable的compareTo方法本来就很好,但这里它被标记为final。 EnumcompareTo 上的默认自然顺序是列出的顺序。

有谁知道为什么 Java 枚举有这个限制?

An enum in Java implements the Comparable interface. It would have been nice to override Comparable's compareTo method, but here it's marked as final. The default natural order on Enum's compareTo is the listed order.

Does anyone know why a Java enums have this restriction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

┈┾☆殇 2024-07-20 10:25:43

为了保持一致性,我想......当您看到 enum 类型时,您就知道事实上它的自然顺序就是声明常量的顺序。

要解决此问题,您可以轻松创建自己的 Comparator 并在需要不同排序时使用它:

enum MyEnum
{
    DOG("woof"),
    CAT("meow");

    String sound;    
    MyEnum(String s) { sound = s; }
}

class MyEnumComparator implements Comparator<MyEnum>
{
    public int compare(MyEnum o1, MyEnum o2)
    {
        return -o1.compareTo(o2); // this flips the order
        return o1.sound.length() - o2.sound.length(); // this compares length
    }
}

您可以直接使用 Comparator

MyEnumComparator comparator = new MyEnumComparator();
int order = comparator.compare(MyEnum.CAT, MyEnum.DOG);

或在集合中使用它或数组:

NavigableSet<MyEnum> set = new TreeSet<MyEnum>(comparator);
MyEnum[] array = MyEnum.values();
Arrays.sort(array, comparator);    

更多信息:

For consistency I guess... when you see an enum type, you know for a fact that its natural ordering is the order in which the constants are declared.

To workaround this, you can easily create your own Comparator<MyEnum> and use it whenever you need a different ordering:

enum MyEnum
{
    DOG("woof"),
    CAT("meow");

    String sound;    
    MyEnum(String s) { sound = s; }
}

class MyEnumComparator implements Comparator<MyEnum>
{
    public int compare(MyEnum o1, MyEnum o2)
    {
        return -o1.compareTo(o2); // this flips the order
        return o1.sound.length() - o2.sound.length(); // this compares length
    }
}

You can use the Comparator directly:

MyEnumComparator comparator = new MyEnumComparator();
int order = comparator.compare(MyEnum.CAT, MyEnum.DOG);

or use it in collections or arrays:

NavigableSet<MyEnum> set = new TreeSet<MyEnum>(comparator);
MyEnum[] array = MyEnum.values();
Arrays.sort(array, comparator);    

Further information:

沫离伤花 2024-07-20 10:25:43

提供使用源代码排序的 CompareTo 的默认实现就可以了; 将其定为最终结果是 Sun 的一个失误。 序数已经说明了声明顺序。 我同意,在大多数情况下,开发人员可以对他们的元素进行逻辑排序,但有时,人们希望以一种使可读性和可维护性至关重要的方式组织源代码。 例如:


  //===== SI BYTES (10^n) =====//

  /** 1,000 bytes. */ KILOBYTE (false, true,  3, "kB"),
  /** 106 bytes. */   MEGABYTE (false, true,  6, "MB"),
  /** 109 bytes. */   GIGABYTE (false, true,  9, "GB"),
  /** 1012 bytes. */  TERABYTE (false, true, 12, "TB"),
  /** 1015 bytes. */  PETABYTE (false, true, 15, "PB"),
  /** 1018 bytes. */  EXABYTE  (false, true, 18, "EB"),
  /** 1021 bytes. */  ZETTABYTE(false, true, 21, "ZB"),
  /** 1024 bytes. */  YOTTABYTE(false, true, 24, "YB"),

  //===== IEC BYTES (2^n) =====//

  /** 1,024 bytes. */ KIBIBYTE(false, false, 10, "KiB"),
  /** 220 bytes. */   MEBIBYTE(false, false, 20, "MiB"),
  /** 230 bytes. */   GIBIBYTE(false, false, 30, "GiB"),
  /** 240 bytes. */   TEBIBYTE(false, false, 40, "TiB"),
  /** 250 bytes. */   PEBIBYTE(false, false, 50, "PiB"),
  /** 260 bytes. */   EXBIBYTE(false, false, 60, "EiB"),
  /** 270 bytes. */   ZEBIBYTE(false, false, 70, "ZiB"),
  /** 280 bytes. */   YOBIBYTE(false, false, 80, "YiB");

上面的排序在源代码中看起来不错,但并不是作者认为的compareTo应该如何工作。 所需的compareTo 行为是按字节数排序。 导致这种情况发生的源代码顺序会降低代码的组织性。

作为枚举的客户,我不在乎作者如何组织他们的源代码。 不过,我确实希望他们的比较算法具有某种意义。 Sun 不必要地让源代码编写者陷入困境。

Providing a default implementation of compareTo that uses the source-code ordering is fine; making it final was a misstep on Sun's part. The ordinal already accounts for declaration order. I agree that in most situations a developer can just logically order their elements, but sometimes one wants the source code organized in a way that makes readability and maintenance to be paramount. For example:


  //===== SI BYTES (10^n) =====//

  /** 1,000 bytes. */ KILOBYTE (false, true,  3, "kB"),
  /** 106 bytes. */   MEGABYTE (false, true,  6, "MB"),
  /** 109 bytes. */   GIGABYTE (false, true,  9, "GB"),
  /** 1012 bytes. */  TERABYTE (false, true, 12, "TB"),
  /** 1015 bytes. */  PETABYTE (false, true, 15, "PB"),
  /** 1018 bytes. */  EXABYTE  (false, true, 18, "EB"),
  /** 1021 bytes. */  ZETTABYTE(false, true, 21, "ZB"),
  /** 1024 bytes. */  YOTTABYTE(false, true, 24, "YB"),

  //===== IEC BYTES (2^n) =====//

  /** 1,024 bytes. */ KIBIBYTE(false, false, 10, "KiB"),
  /** 220 bytes. */   MEBIBYTE(false, false, 20, "MiB"),
  /** 230 bytes. */   GIBIBYTE(false, false, 30, "GiB"),
  /** 240 bytes. */   TEBIBYTE(false, false, 40, "TiB"),
  /** 250 bytes. */   PEBIBYTE(false, false, 50, "PiB"),
  /** 260 bytes. */   EXBIBYTE(false, false, 60, "EiB"),
  /** 270 bytes. */   ZEBIBYTE(false, false, 70, "ZiB"),
  /** 280 bytes. */   YOBIBYTE(false, false, 80, "YiB");

The above ordering looks good in source code, but is not how the author believes the compareTo should work. The desired compareTo behavior is to have ordering be by number of bytes. The source-code ordering that would make that happen degrades the organization of the code.

As a client of an enumeration i could not care less how the author organized their source code. I do want their comparison algorithm to make some kind of sense, though. Sun has unnecessarily put source code writers in a bind.

偏闹i 2024-07-20 10:25:43

枚举值根据声明的顺序精确地进行逻辑排序。 这是 Java 语言规范的一部分。 因此,只有当枚举值是同一枚举的成员时才能进行比较。 规范希望进一步保证compareTo()返回的可比较顺序与声明值的顺序相同。 这就是枚举的定义。

Enumeration values are precisely ordered logically according to the order they are declared. This is part of the Java language specification. Therefore it follows that enumeration values can only be compared if they are members of the same Enum. The specification wants to further guarantee that the comparable order as returned by compareTo() is the same as the order in which the values were declared. This is the very definition of an enumeration.

温暖的光 2024-07-20 10:25:43

一种可能的解释是 compareTo 应该与 equals 一致。

枚举的 equals 应该与身份相等 (==) 一致。

如果 compareTo 是非最终的,则可能会使用与 equals 不一致的行为来覆盖它,这是非常违反直觉的。

One possible explanation is that compareTo should be consistent with equals.

And equals for enums should be consistent with identity equality (==).

If compareTo where to be non-final it would be possible to override it with a behaviour which was not consistent with equals, which would be very counter-intuitive.

情栀口红 2024-07-20 10:25:43

如果您想更改枚举元素的自然顺序,请更改它们在源代码中的顺序。

If you want to change the natural order of your enum’s elements, change their order in the source code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文