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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/519788/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:42:54  来源:igfitidea点击:

Why is compareTo on an Enum final in Java?

javaenumscomparablecompareto

提问by neu242

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

Java 中的枚举实现了该Comparable接口。覆盖ComparablecompareTo方法会很好,但在这里它被标记为 final。在默认的自然秩序EnumcompareTo是所列出的顺序。

Does anyone know why a Java enums have this restriction?

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

采纳答案by Zach Scrivena

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

为了一致性,我猜......当你看到一个enum类型时,你知道一个事实,它的自然顺序是声明常量的顺序。

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

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

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 Comparatordirectly:

您可以Comparator直接使用:

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

or use it in collections or arrays:

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

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

Further information:

更多信息:

回答by Bombe

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

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

回答by Martin OConnor

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.

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

回答by Thomas Paine

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:

提供使用源代码排序的 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");

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.

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

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.

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

回答by Lii

One possible explanation is that compareToshould be consistent with equals.

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

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

并且equals对于枚举应该与身份相等 ( ==)一致。

If compareTowhere 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.

如果compareTowhere 是非最终的,则可以用与 不一致的行为覆盖它equals,这将非常违反直觉。