enhanced enums - back from the dead?
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Thu Dec 6 19:23:05 UTC 2018
On 06/12/2018 16:53, forax at univ-mlv.fr wrote:
>
> ----- Mail original -----
>> De: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
>> À: "Remi Forax" <forax at univ-mlv.fr>
>> Cc: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
>> Envoyé: Jeudi 6 Décembre 2018 09:54:09
>> Objet: Re: enhanced enums - back from the dead?
>> Hi Remi, some comments inline.
>>
>> On 05/12/2018 21:43, Remi Forax wrote:
>>> Hi Maurizio,
>>> i think you have overlook the fact that raw types and inference also doesn't
>>> play well together.
>> As I said, I've played with this quite a bit and came out convinced that
>> usability wise it's good. Note that in the proposed model, enum
>> constants will have full generic types - e.g. Foo<String>; it's only
>> when you go to the supertype that the type system will say Enum<Foo>.
>> But this will only be used by APIs accepting some Enum<T> - so we're
>> fine, and this actually guarantees same inference results as before
>> generification of a given enum.
> yes, i'm worried about Foo.values()
>
> public enum Foo<T extends Comparable<T>> implements Comparable<Foo<T>> {
> S<>(""), I<>(42); // JEP 301 mentions the diamond syntax
>
> private final T t;
>
> private Foo(T t) {
> this.t = t;
> }
>
> @Override
> public int compareTo(Foo<T> o) {
> return t.compareTo(o.t);
> }
>
> public static void main(String[] args) {
> Arrays.stream(Foo.values()).sorted().forEach(System.out::println);
> }
> }
Can't quite understand what you mean - the code above is flawed in
different ways; first you can't implement Comparable<Foo<T>> - as Enum
already does that and with Comparable<Foo> in this case (because of the
new treatment).
Secondly, you can't override compareTo - which is final in enum.
So, the correct example is this:
import java.util.*;
enum Foo<T extends Comparable<T>> implements Comparable<Foo> {
S<String>(""), I<Integer>(42); // JEP 301 mentions the diamond syntax
private final T t;
private Foo(T t) {
this.t = t;
}
public static void main(String[] args) {
Arrays.stream(Foo.values()).sorted().forEach(System.out::println);
}
}
Which compiles with no issues.
>
>>> accessibility:
>>> Widening the type is usually a big No because of the security implication. The
>>> fact that the same code code has no security bug with version n but a security
>>> hole with version n + 1 scares me.
>> What scenario do you have in mind regarding enum constant pseudo-inner classes?
> any scenario that is using a Lookup object
Still not getting what is the security implication; one thing is to say
that you can reflectively inspect a class where you could not before;
another is that doing so represents a vulnerability. The proposed rule
says that the enum constant class gets same visibility as parent. So you
are really saying that some constant class contains _security sensitive_
details, and that users relied on an *unspecified* compiler behavior
that protected them, as javac made the class package-private. That seems
a pretty strange argument.
>
>>> source compatibility:
>>> It's may not be a big issue because the JDK source doesn't use 'var'. If a code
>>> uses 'var' the sharp type will propagate more, so the JDK is not perhaps the
>>> best code to test.
>>>
>>> friend or foe:
>>> the rules for raw types are brutal as you said, but it's by design, it offers
>>> maximum compatibility and doesn't allow to mix raw and generic type easily so
>>> my students detect the missing angle brackets easily (IntelliJ still doesn't
>>> warn about missing angle brackets by default :( )
>>>
>>>
>>> Now about your example, instead of being functional and wanted each Option to
>>> type their argument, you can use ugly side effects instead.
>>> So the idea is to use a temporary class instead of a Map to store the data
>>> associated with an option. So an Option is something that takes a chunk of the
>>> command line arguments and do a side effect on the field of an instance of that
>>> temporary class.
>> Sure, there might be other ways to get there; what I did, I did it to
>> test usage of generic enums in a real world code base.
> it seems to be "the use case" for generics enum.
I get that you do not like the feature :-)
Other use cases have been discussed here:
http://mail.openjdk.java.net/pipermail/amber-dev/2017-April/000173.html
rest assured, the JEP might bear my name, but we're not looking into
this to make javac code better.
Maurizio
>
>> Maurizio
> Rémi
>
>>> public class LineParsing {
>>> private final HashMap<String, Consumer<? super Iterator<String>>> actionMap =
>>> new HashMap<>();
>>>
>>> public LineParsing with(String option, Consumer<? super Iterator<String>>
>>> action) {
>>> actionMap.put(option, action);
>>> return this;
>>> }
>>>
>>> public void parse(List<String> args) {
>>> var it = args.iterator();
>>> while(it.hasNext()) {
>>> actionMap.get(it.next()).accept(it);
>>> }
>>> }
>>>
>>> public static void main(String[] args) {
>>> var bean = new Object() {
>>> Path input = Path.of("input.txt");
>>> boolean all = false;
>>> };
>>>
>>> new LineParsing()
>>> .with("-input", it -> bean.input = Path.of(it.next()))
>>> .with("-all", it -> bean.all = true)
>>> .parse(List.of(args));
>>> }
>>> }
>>>
>>> regards,
>>> Rémi
>>>
>>>
>>> ----- Mail original -----
>>>> De: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
>>>> À: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
>>>> Envoyé: Mercredi 5 Décembre 2018 17:14:59
>>>> Objet: enhanced enums - back from the dead?
>>>> Hi,
>>>> as mentioned in [1], the work on enhanced enum stopped while ago as we
>>>> have found some interoperability issues between generic enums and
>>>> standard enum APIs such as EnumSet/EnumMap.
>>>>
>>>> Recently, we have discussed a possible approach that might get us out of
>>>> the woods, which is described in greater details here:
>>>>
>>>> http://cr.openjdk.java.net/~mcimadamore/amber/enhanced-enums.html
>>>>
>>>> We have done some internal testing to convince ourselves that, from an
>>>> operational perspective, where we end up is indeed good. Some external
>>>> validation might also be very helpful, which is why we're also in the
>>>> process of releasing the internal patch we have tested internally in the
>>>> 'enhanced-enums' amber branch (we'll need to polish it a little :-)).
>>>>
>>>> Assuming that, usability-wise, our story ticks all the boxes, I think it
>>>> might be worth discussing a few points:
>>>>
>>>> * Do we still like the features described in JEP 301, from an
>>>> expressiveness point of view?
>>>>
>>>> * Both features described in JEP 301 require some sort of massaging. On
>>>> the one hand sharper typing of enum constants has to take care of binary
>>>> compatibility of enum constant subclasses into account (for this reason
>>>> we redefine accessibility of said subclasses along with their binary
>>>> names). On the other hand, with the newly proposed approach, generic
>>>> enums also need some language aid (treatment of raw enum constants
>>>> supertypes). Do we feel that the steps needed in order to accommodate
>>>> these sharp edges are worth the increase in expressive power delivered
>>>> by JEP 301?
>>>>
>>>> * Our proposed treatment for generic enums raises an additional, more
>>>> philosophical, question: what are raw types *for* and how happy are we
>>>> in seeing more of them (in the form of raw enum types)?
>>>>
>>>> Cheers
>>>> Maurizio
>>>>
>>>> [1] -
>>>> http://mail.openjdk.java.net/pipermail/amber-spec-experts/2017-May/000041.html
More information about the amber-spec-observers
mailing list