This discussion is archived
1 2 Previous Next 16 Replies Latest reply: Sep 1, 2010 5:46 AM by 843793 RSS

Parameterized enum Instantation

843793 Newbie
Currently Being Moderated
Sorry if this duplicated elsewhere, but the search function isn't working for me, and some extensive Googling turned up nothing. I found similiar issues, but none address my specific one.

I'd like to use a type parameter when instantiating an enum. I'm not sure if I just don't know the syntax or it isn't supported by the language. For example, I want to be able to write something like:
import java.lang.reflect.Constructor;

public enum CommonContainersr<T extends ContainerType> implements ContainerDescriptor<T> {

    BOTTLE<ImpermeableContainer>(ImpermeableContainer.class, 10, "Water"),
    BASKET<PermeableContainer>(PermeableContainer.class, 54, "Potpurri"),
    BOX<FooContainer>(FooContainer.class, 123, "I'm a box!");
    
    public final Constructor containerConstructor;
    public final int volume;
    public final String label;

    public Container(Class<T> container, int volume, String label) {
        containerConstructor = contained.getConstructor(int.class, String.class, Object.class);
        this.volume = volume;
        this.label = label;
    }

    public T createContainer(Object contents) {
        return containerConstructor.newInstance(volume, label, contents);
    }
}
without resorting to
public enum CommonContainers implements ContainerDescriptor<ContainerType>
    BOTTLE(...) {
        public ImpermeableContainer createImpermeableContainer(Object contents) {
            return (ImpermeableContainer)createContainer(volume, label, contents);
        }
    },
    BASKET(...) {
        public PermeableContainer createPermeableContainer ...
    };
...
}
Shouldn't enums be able to have type parameters that are specified when the enum constant is constructed?

Edited by: MutantPlatypus on Aug 24, 2010 11:29 PM
  • 1. Re: Parameterized enum Instantation
    EJP Guru
    Currently Being Moderated
    'It is a compile-time error if the ClassType names the class Enum or any invocation of it.' [JLS #8.1.4|http://java.sun.com/docs/books/jls/third_edition/html/classes.html#299360]
  • 2. Re: Parameterized enum Instantation
    843793 Newbie
    Currently Being Moderated
    ejp wrote:
    'It is a compile-time error if the ClassType names the class Enum or any invocation of it.' [JLS #8.1.4|http://java.sun.com/docs/books/jls/third_edition/html/classes.html#299360]
    Right, so its illegal to explicitly extend the Enum class or any enum types. I need more help seeing how that applies here.
  • 3. Re: Parameterized enum Instantation
    EJP Guru
    Currently Being Moderated
    Sorry, wrong quote! It's disallowed by the syntax as specified in #8.1 and 8.9.
  • 4. Re: Parameterized enum Instantation
    843793 Newbie
    Currently Being Moderated
    Ah, yup, not supported by the syntax. But... isn't this possible? I suppose this turns into a request for enhancement now. Couldn't this be made to work? All you would need is the syntax support for the parametrized constructor call. I don't see any fundamental rules this would break.

    It would look like:
    public <T extends ContainerType> enum CommonContainers implements ContainerDescriptor<T> {
     
        BOTTLE<ImpermeableContainer>(ImpermeableContainer.class, 10, "Water"),
        BASKET<PermeableContainer>(PermeableContainer.class, 54, "Potpurri"),
        BOX<FooContainer>(FooContainer.class, 123, "I'm a box!");
        
        public final Constructor<T> containerConstructor;
        public final int volume;
        public final String label;
     
        public Container(Class<T> container, int volume, String label) {
            containerConstructor = contained.getConstructor(int.class, String.class, Object.class);
            this.volume = volume;
            this.label = label;
        }
     
        public T createContainer(Object contents) {
            return containerConstructor.newInstance(volume, label, contents);
        }
    }
    Note the placement of the type parameters, so as not to be like a generic class. The constants would still be referenced like
    CommonContainer.BOTTLE
    without type parameters, as these have already been provided at compile type.
  • 5. Re: Parameterized enum Instantation
    EJP Guru
    Currently Being Moderated
    As you can't instantiate Enums there is no point.
  • 6. Re: Parameterized enum Instantation
    843793 Newbie
    Currently Being Moderated
    ejp wrote:
    As you can't instantiate Enums there is no point.
    What? I fail to follow your reasoning.

    I'm not saying the requested feature is useful (I'd have to think about that a bit more), but I don't see why it would be impossible? Basically you'd define a per-value concrete type for the type argument defined on the enum class definition.
  • 7. Re: Parameterized enum Instantation
    EJP Guru
    Currently Being Moderated
    The point being?
  • 8. Re: Parameterized enum Instantation
    843793 Newbie
    Currently Being Moderated
    ejp wrote:
    The point being?
    I see a point in the suggestion and I don't see why it would be impossible to tweak the JLS to allow this.

    You claim that it's impossible and I don't understand why.

    enums are implicitly instantiated for their values (and can't be instantiated explicitly). So why not provide a type parameter to an enum and specify a concrete type for different values?
  • 9. Re: Parameterized enum Instantation
    EJP Guru
    Currently Being Moderated
    I don't see why it would be impossible to tweak the JLS to allow this.
    You claim that it's impossible
    I most certainly claimed no such thing.
    So why not provide a type parameter to an enum and specify a concrete type for different values?
    I don't know: why not? Why are you asking me? The decision has nothing to do with me.

    I'm just asking for a concrete motivation. I haven't been given one yet.
  • 10. Re: Parameterized enum Instantation
    843793 Newbie
    Currently Being Moderated
    ejp wrote:
    I don't see why it would be impossible to tweak the JLS to allow this.
    You claim that it's impossible
    I most certainly claimed no such thing.
    Correct.

    You claimed that it's impossible to instantiate the enum when the question was already at the point of tweaking the Java language.

    So why not provide a type parameter to an enum and specify a concrete type for different values?
    I don't know: why not? Why are you asking me? The decision has nothing to do with me.
    I was asking the question because I interpreted your "there's no point" (wrongly?) as "there's no point in modifying the Java language to allow this".
    I'm just asking for a concrete motivation. I haven't been given one yet.
    The example posted looks like a pretty concrete motivation to me. With the example enum I can easily create a ContainerType object (of any type if I don't care), but I can also create specific FooContainer by using CommonContainers.BOX.createConteiner(). That way I can use the enum and still be typesafe with APIs that expect a FooContainer.
  • 11. Re: Parameterized enum Instantation
    843793 Newbie
    Currently Being Moderated
    JoachimSauer wrote:
    ejp wrote:
    I'm just asking for a concrete motivation. I haven't been given one yet.
    The example posted looks like a pretty concrete motivation to me. With the example enum I can easily create a ContainerType object (of any type if I don't care), but I can also create specific FooContainer by using CommonContainers.BOX.createConteiner(). That way I can use the enum and still be typesafe with APIs that expect a FooContainer.
    Exactly. I'm aware that this may be taking enums somewhere they aren't supposed to go, or may be taking generics just way too far, which is why I posited the question on the forums. I'm just trying to enforce type safety at compile time with this specific case. There may be some other, suitable, way to do this, but enums just seemed to be so well suited to this.

    Basically, my motivation for this is to provide an enum that acts as a "template" (for lack of a better word) of sorts. I have a class, and there are certain combinations of field states that I KNOW that users of this class will commonly be referring to. The constants provide an easy way to instantiate the class and place it in the proper state for immediate use, as well as provide a common identifier for that specific descriptor.

    Now, I know this could be done without the enum facility, (I've already decided I want the type safety more than I want the enum features) but its just handy being able to switch on the constants, use them in EnumSets and Maps, and use the other facilities provided by the Enum class.
  • 12. Re: Parameterized enum Instantation
    DrClap Expert
    Currently Being Moderated
    MutantPlatypus wrote:
    Basically, my motivation for this is to provide an enum that acts as a "template" (for lack of a better word) of sorts. I have a class, and there are certain combinations of field states that I KNOW that users of this class will commonly be referring to. The constants provide an easy way to instantiate the class and place it in the proper state for immediate use, as well as provide a common identifier for that specific descriptor.

    Now, I know this could be done without the enum facility, (I've already decided I want the type safety more than I want the enum features) but its just handy being able to switch on the constants, use them in EnumSets and Maps, and use the other facilities provided by the Enum class.
    So this is basically the factory method pattern? It's quite common for a factory method to be static, so it isn't much of a leap to make the enum element itself be a factory.
  • 13. Re: Parameterized enum Instantation
    EJP Guru
    Currently Being Moderated
    You claimed that it's impossible to instantiate the enum
    I did. It is. You can't do new MyEnum<Integer>, or even new MyEnum(). That's not just a 'claim', it's a fact.

    But I was missing the point. The usage the OP is proposing is something else, a class that has differently parameterized instances of itself declared as members. Rather like:
    class MyEnum<T>
    {
      MyEnum<Integer> myIntegerEnum;
      MyEnum<String> myStringEnum;
    }
  • 14. Re: Parameterized enum Instantation
    843793 Newbie
    Currently Being Moderated
    ejp wrote:
    You claimed that it's impossible to instantiate the enum
    I did. It is. You can't do new MyEnum<Integer>, or even new MyEnum(). That's not just a 'claim', it's a fact.
    Of course you are right.

    It's just that in my mind objects don't exist without instantiation and the enum values are objects (and they do get to execute the constructor), so I'd say (in my in-precise language) that there is some instantiation involved in declaring enum values. But that's beside the point.
    But I was missing the point. The usage the OP is proposing is something else, a class that has differently parameterized instances of itself declared as members. Rather like:
    class MyEnum<T>
    {
    MyEnum<Integer> myIntegerEnum;
    MyEnum<String> myStringEnum;
    }
    Yes, that's pretty much what he wanted (or at least what I understood that he wanted), except not in a "normal" class, but in an enum with all the other enum features/restrictions still in place.
1 2 Previous Next