[External] : Re: JEP proposal: Generic/Interfaced Enums as annotation attributes
Alex Buckley
alex.buckley at oracle.com
Wed Feb 16 01:40:35 UTC 2022
OK, I see the abstraction you want. There are two ways of looking at it:
1. An annotation interface element ought to be able to be declared with
an interface type, not just the primitive types, String, enum types,
etc. Per Brian, this takes the element outside the realm of compile-time
constants, so it's not in the spirit of annotations.
2. An enum class ought to be subclassable by another enum class.
Qualititable would be an enum class with no constants and one abstract
method, and Q1 and Q2 would be enum classes that extend Qualititable.
Your Quality annotation interface would declare `Qualititable value()`
(the element has an enum class type, as required!) and you would write
@Quality(Q1.LOW_QUALITY) and @Quality(Q2.POOR_QUALITY). However, the JSR
that created enum classes, JSR 201, included a FAQ that basically says
subclassing is not in the spirit of enums:
-----
With the Typesafe Enum pattern described in Effective Java, it is
possible to subclass an enumerated type. Why is this not allowed by the
language feature?
The semantics of inheritance for enum types is too confusing. People
expect subclasses to contain the enumeration constants from both the
superclass and the subclass, but they contain only the subclass
constants. Further, the compiler generates two static methods for each
enum class providing operations on the entire class (values() and
valueOf(String)). These methods are defined using the list of constants
found in the enum declaration, hence subclassing would break them. More
seriously, allowing subclassing of enums would render switch statements
ambiguous if multiple subclasses of an enum class contained enum
constants with the same simple name. All things considered, the
complexity inherent in allowing subclassing is too great to justify it.
-----
It's easy to look at these constraints and say "Annotations and enums in
Java would be more successful if the constraints were relaxed", but good
design adds value faster than it adds cost, and designing away the
constraints would (for sure) add cost faster than it adds value.
Alex
On 2/15/2022 4:26 PM, Marc Miranda wrote:
> But you need to know the type beforehand, it cannot be a
> generic/interfaced enum
>
> Imagine you are designing an API and you want to let the user to specify
> the Quality, but you don't want to impose him the particular enum so he
> can add behaviour (implementing the quality).
> In this case, you would like to define your Quality annotation so it
> accepts any enum that implements a isEnoughQuality()
>
> On the API side:
> ******************
>
> @interface Quality {
> Enum<Qualititable> value();
> }
>
> interface Qualititable {
> boolean isEnoughQuality();
> }
>
> On the Client User Side:
> ****************************
>
> @RequiredArgsConstructor
> public enum MyCustomQualities implement Qualiitiable {
> MY_CUSTOM_LOW_QUALITY(() -> false),
> MY_CUSTOM_MEDIUM_QUALITY(() -> RandomUtils.getBoolean()),
> MY_CUSTOM_HIGH_QUALITY(() -> true);
>
> private final Supplier<Boolean> qualityEvaluator;
>
> @Override
> public isEnoughQuality() {
> return qualityEvaluator.get();
> }
> }
>
>
> Then you could use it like
>
> @Quality(MyCustomQualities.LOW)
> public void class Test {
> (...)
> }
>
> El mar, 15 feb 2022 a las 23:19, Alex Buckley (<alex.buckley at oracle.com
> <mailto:alex.buckley at oracle.com>>) escribió:
>
> On 2/15/2022 2:04 PM, Marc Miranda wrote:
> > I am not sure we are talking of the same use case.
> > In my case I am fine with non-generic enums, it is just about letting
> > annotation attributes pass an enum reference
>
> But an annotation can already have enum-typed elements. Here's an
> example from JLS 9.6.1:
>
> @interface Quality {
> enum Level { BAD, INDIFFERENT, GOOD }
> Level value();
> }
>
> @Quality(Quality.Level.BAD) public class Foo {}
>
> Alex
>
More information about the amber-dev
mailing list