Pergunta

Um enum em Java implementa a interface Comparable. Teria sido bom método Comparable substituição de compareTo, mas aqui ele é marcado como final. O padrão ordem natural em Enum de compareTo é a ordem listada.

Alguém sabe por que um enums Java tem essa restrição?

Foi útil?

Solução

Para consistência eu acho ... quando você vê um tipo enum, você sabe para um fato que sua ordenação natural é a ordem em que as constantes são declarados.

Para resolver isso, você pode facilmente criar o seu próprio Comparator<MyEnum> e usá-lo sempre que precisar de uma ordem diferente:

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
    }
}

Você pode usar o Comparator diretamente:

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

ou usá-lo em coleções ou matrizes:

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

Mais informações:

Outras dicas

Fornecer uma implementação padrão de compareTo que utiliza a ordenação de código-fonte é bom; tornando-final foi um passo em falso por parte do Sol. O ordinal já responde por ordem de declaração. Concordo que na maioria das situações um desenvolvedor pode apenas logicamente encomendar os seus elementos, mas às vezes se quer o código fonte organizado de uma forma que faz com que a legibilidade e manutenção a ser primordial. Por exemplo:


  //===== 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");

A ordenação acima parece ser bom no código fonte, mas não é como o autor acredita que o compareTo deve funcionar. O comportamento compareTo desejado é ter ordenação ser pelo número de bytes. A ordenação de código-fonte que iria fazer isso acontecer degrada a organização do código.

Como um cliente de uma enumeração eu não poderia me importar menos como o autor organizou o seu código-fonte. Eu quero o seu algoritmo de comparação de fazer algum tipo de sentido, no entanto. Sun tem desnecessariamente colocar escritores de código fonte em um ligamento.

Os valores de enumeração são precisamente ordenado logicamente de acordo com a ordem em que são declaradas. Esta é parte da especificação da linguagem Java. Portanto segue-se que valores de enumeração só pode ser comparado se eles são membros da mesma Enum. A especificação quer ainda garantia de que a ordem comparável como retornado por compareTo () é a mesma que a ordem em que os valores foram declaradas. Esta é a própria definição de uma enumeração.

Uma possível explicação é que compareTo deve ser consistente com equals.

E equals para enums deve ser consistente com a igualdade de identidade (==).

Se compareTo onde a ser não-de-final seria possível substituí-lo com um comportamento que não era consistente com equals, o que seria muito contra-intuitivo.

Se você quiser alterar a ordem natural de elementos do seu enum, alterar a sua ordem no código-fonte.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top