Java Enum definition
I thought I understood Java generics pretty well, but then I came across the following in java.lang.Enum:
Could someone explain how to interpret this type parameter? Bonus points for providing other examples of where a similar type parameter could be used.
8 Answers 8
It means that the type argument for enum has to derive from an enum which itself has the same type argument. How can this happen? By making the type argument the new type itself. So if I’ve got an enum called StatusCode, it would be equivalent to:
public class StatusCode extends Enum
Now if you check the constraints, we’ve got Enum — so E=StatusCode . Let’s check: does E extend Enum ? Yes! We’re okay.
You may well be asking yourself what the point of this is 🙂 Well, it means that the API for Enum can refer to itself — for instance, being able to say that Enum implements Comparable . The base class is able to do the comparisons (in the case of enums) but it can make sure that it only compares the right kind of enums with each other. (EDIT: Well, nearly — see the edit at the bottom.)
I’ve used something similar in my C# port of ProtocolBuffers. There are «messages» (immutable) and «builders» (mutable, used to build a message) — and they come as pairs of types. The interfaces involved are:
public interface IBuilder where TMessage : IMessage where TBuilder : IBuilder public interface IMessage where TMessage : IMessage where TBuilder : IBuilder
This means that from a message you can get an appropriate builder (e.g. to take a copy of a message and change some bits) and from a builder you can get an appropriate message when you’ve finished building it. It’s a good job users of the API don’t need to actually care about this though — it’s horrendously complicated, and took several iterations to get to where it is.
EDIT: Note that this doesn’t stop you from creating odd types which use a type argument which itself is okay, but which isn’t the same type. The purpose is to give benefits in the right case rather than protect you from the wrong case.
So if Enum weren’t handled «specially» in Java anyway, you could (as noted in comments) create the following types:
public class First extends Enum <> public class Second extends Enum <>
Second would implement Comparable rather than Comparable . but First itself would be fine.
Java cast to enum class
* Информация для продвинутых юзеров. На самом деле возможно ограниченное наследование от Enum. Подробнее здесь: https://kibungo.livejournal.com/19999.html Пример наследования и переопределения общего метода:
public enum MyEnum < VAL1 < public int returnMyVal()< return 20; >>, VAL2; public int returnMyVal() < return 10; >> ------------------------ System.out.println(MyEnum.VAL1.returnMyVal()) // 20 System.out.println(MyEnum.VAL2.returnMyVal()) // 10
«По сравнению с обычными классами, на Enum наложили одно серьезное ограничение — от него невозможно наследоваться.» Что за бред вы пишете?! Все перечисления изначально неявно расширяют класс java.lang.Enum, а поскольку в Java нету множественного наследования, то и расширять enum уже больше ничего не может.
В статье enum в коде с маленькой буквы, в комментариях к коду — Enum с большой Почему не говорится, что это разные вещи? Если у нас несколько enum`ов с перечислениями в приложении и нам нужно передать один из них как аргумент в метод можно сделать просто так someMethod(Enum e) < и здесь написать условие для выбора одного из enum`ов >Т.е. не нужно приводить все enum`ы к единому интерфейсу или абстрактному классу, чтобы выбрать один из enum`ов Как я понял Enum(тот который с большой буквы) — это что-то типа пустого интерфейса для всех enum`ов
@Override public String toString() < return "DayOfWeek';
В коде приведенного примера про школьника есть ошибка: задано поле private ScholarSchedule schedule, но сеттер для него не прописан, а так как оно изначально не инициализировано, получаете NullPointerException. Добавьте сеттер (либо просто сделайте это поле public, что есть костыль) для задания значения:
public void setSchedule(ScholarSchedule schedule)
Ну или, в конце концов, поместите метод main в класс Scholar (видимо так и задумывалось автором примера изначально), тогда он будет иметь доступ к private ScholarSchedule schedule и сможет инициализировать его надлежащим образом.
In an enum class, how can one cast values as dates?
In an enum class, how can one cast a value as the type java.util.date ? The enum still has to have a name. I have tried:
ENUM_OPTION1(Date(10000000000L))
But I got an error saying that "Symbol Date(long) wasn't recognized", even though I imported the class at the top of my file.
FYI, java.util.Date is a terrible class that was supplanted years ago by the java.time classes, specifically Instant .
1 Answer 1
new Date( … )
Use new to instantiate a java.util.Date .
ENUM_OPTION1( new Date( 10_000_000_000L ) )
FYI, java.util.Date is a terrible class that was supplanted years ago by the java.time classes, specifically Instant .
Full example
Add a constructor on your enum. On each instance of the enum you declare, call the constructor. To that constructor, pass the specific date. See tutorial by Oracle.
public enum History < US_DECLARATION_OF_INDEPENDENCE( LocalDate.of( 1776 , Month.July , 4 ) ) , US_CONSTITIUTION_APPROVED( LocalDate.of( 1787 , 9 , 17 ) ) ; private LocalDate localDate ; // Constructor public History( LocalDate ld ) < Objects.requireNonNull( ld ) ; this.localDate = ld ; >// Getter public LocalDate getLocalDate() < return this.localDate ; >>
To use this enum, call the instance method on one of the named constant instances.
LocalDate ld = History.US_DECLARATION_OF_INDEPENDENCE.getLocalDate() ;
How can I declare enums using java
As for enums, there're many other correct answers below by now (and a must read link above) . Just wanted to add that if your class holds some constants like in your example (I am not talking about enums right now. ) you can simply define interface this way: public interface TestConstants < String TEST = "test"; /*. */ >Interface 'fields' are implicitly public static.
@Arturs Licis: Using an interface to hold constants is an anti-pattern. An interface is meant to define behavior. Use a regular class with a private constructor to hold constants. Static imports can be used to access the constants without putting the class name before.
@JB Nizet: Completely agree, that's why I said 'I am not talking about enums right now. ' I just showed a more accurate way to declare 'constants holder' (interface versus class).
@Arturs Licis: My point is that you shouldn't use an interface to hold constants, but a class: public class TestConstants rather than public interface TestConstants. If you completely agree with me, why do you give this advice to the OP?
6 Answers 6
public enum MyEnum < ONE(1), TWO(2); private int value; private MyEnum(int value) < this.value = value; >public int getValue() < return value; >>
In short - you can define any number of parameters for the enum as long as you provide constructor arguments (and set the values to the respective fields)
As Scott noted - the official enum documentation gives you the answer. Always start from the official documentation of language features and constructs.
Update: For strings the only difference is that your constructor argument is String , and you declare enums with TEST("test")